python枚举类的意义_用于ORM目的的python枚举类
編輯問(wèn)題
我正在嘗試創(chuàng)建一個(gè)類(lèi)工廠,它可以生成具有以下屬性的枚舉類(lèi):
>從列表中初始化類(lèi)
允許值(即,它)
自動(dòng)生成!).
> Class創(chuàng)建自己的一個(gè)實(shí)例
對(duì)于每個(gè)允許的值.
>類(lèi)不允許創(chuàng)建
任何其他實(shí)例一旦
上述步驟已完成(任何嘗試
這樣做會(huì)導(dǎo)致異常).
>類(lèi)實(shí)例提供了一種方法
這個(gè),給定一個(gè)值,返回一個(gè)
參考相應(yīng)的
實(shí)例.
>類(lèi)實(shí)例只有兩個(gè)
屬性:id和value.該
屬性id自動(dòng)遞增
每個(gè)新實(shí)例;屬性
value是實(shí)例的值
代表.
>類(lèi)是可迭代的.我更喜歡
使用the accepted
answer to another SO question實(shí)現(xiàn)這一點(diǎn)
(具體來(lái)說(shuō),通過(guò)利用課程
注冊(cè)表和定義iter
我的元類(lèi)中的方法
枚舉類(lèi)是實(shí)例).
這就是我正在尋找的.請(qǐng)將原始文本(下方)視為問(wèn)題的背景.很抱歉從一開(kāi)始就不清楚.
更新的答案
我對(duì)aaronasterling的非常有用的答案做了一些修改.我以為我會(huì)在這里展示,以便其他人可以受益,所以如果我做錯(cuò)了,我會(huì)收到更多評(píng)論:)
我做的修改是:
(0)移植到p3k(iteritems – > items,元類(lèi) – >’metaclass =’,無(wú)需指定對(duì)象作為基類(lèi))
(1)將實(shí)例方法更改為@classmethod(現(xiàn)在我不需要對(duì)象來(lái)調(diào)用它,只需要類(lèi))
(2)我不是一舉填充_registry,而是每次構(gòu)造一個(gè)新元素時(shí)都更新它.這意味著我可以使用它的長(zhǎng)度來(lái)設(shè)置id,所以我擺脫了_next_id屬性.它也適用于我計(jì)劃的擴(kuò)展(見(jiàn)下文).
(3)從enum()中刪除了classname參數(shù).畢竟,該類(lèi)名將是一個(gè)本地名稱;無(wú)論如何,全局名稱必須單獨(dú)設(shè)置.所以我使用了一個(gè)虛擬’XXX’作為本地類(lèi)名.我有點(diǎn)擔(dān)心第二次調(diào)用該函數(shù)時(shí)會(huì)發(fā)生什么,但它似乎有效.如果有人知道原因,請(qǐng)告訴我.如果這是一個(gè)壞主意,我當(dāng)然可以在每次調(diào)用時(shí)自動(dòng)生成一個(gè)新的本地類(lèi)名.
(4)擴(kuò)展此類(lèi)以允許用戶添加新的枚舉元素的選項(xiàng).具體來(lái)說(shuō),如果使用不存在的值調(diào)用instance(),則會(huì)創(chuàng)建相應(yīng)的對(duì)象,然后由該方法返回.如果我從解析文件中獲取大量枚舉值,這將非常有用.
def enum(values):
class EnumType(metaclass = IterRegistry):
_registry = {}
def __init__(self, value):
self.value = value
self.id = len(type(self)._registry)
type(self)._registry[value] = self
def __repr__(self):
return self.value
@classmethod
def instance(cls, value):
return cls._registry[value]
cls = type('XXX', (EnumType, ), {})
for value in values:
cls(value)
def __new__(cls, value):
if value in cls._registry:
return cls._registry[value]
else:
if cls.frozen:
raise TypeError('No more instances allowed')
else:
return object.__new__(cls)
cls.__new__ = staticmethod(__new__)
return cls
原文
我使用SQLAlchemy作為對(duì)象關(guān)系映射工具.它允許我將類(lèi)映射到SQL數(shù)據(jù)庫(kù)中的表.
我有幾節(jié)課.一個(gè)類(lèi)(Book)是具有一些實(shí)例數(shù)據(jù)的典型類(lèi).其他(流派,類(lèi)型,封面等)都是基本的枚舉類(lèi)型;例如,流派只能是’科幻’,’浪漫’,’漫畫(huà)’,’科學(xué)’;封面只能是“硬”,“軟”;等等. Book與其他每個(gè)類(lèi)之間存在多對(duì)一的關(guān)系.
我想半自動(dòng)生成每個(gè)枚舉樣式的類(lèi).請(qǐng)注意,SQLAlchemy要求’scifi’表示為類(lèi)Genre的實(shí)例;換句話說(shuō),簡(jiǎn)單地定義Genre.scifi = 0,Genre.romance = 1等是行不通的.
我嘗試編寫(xiě)一個(gè)元類(lèi)枚舉,它接受類(lèi)的名稱和允許值列表作為參數(shù).我希望如此
Genre = enum('Genre', ['scifi', 'romance', 'comic', 'science'])
會(huì)創(chuàng)建一個(gè)允許這些特定值的類(lèi),并且還可以創(chuàng)建我需要的每個(gè)對(duì)象:類(lèi)型(‘科幻’),流派(‘浪漫’)等.
但我被卡住了.一個(gè)特別的問(wèn)題是,在ORM意識(shí)到這個(gè)類(lèi)之前我無(wú)法創(chuàng)建Genre(‘scifi’);另一方面,當(dāng)ORM知道Genre時(shí),我們不再是類(lèi)構(gòu)造函數(shù)了.
另外,我不確定我的方法是好的開(kāi)始.
任何意見(jiàn),將不勝感激.
解決方法:
基于更新的新答案
我認(rèn)為這滿足了您所有指定的要求.如果沒(méi)有,我們可以添加你需要的任何東西.
def enum(classname, values):
class EnumMeta(type):
def __iter__(cls):
return cls._instances.itervalues()
class EnumType(object):
__metaclass__ = EnumMeta
_instances = {}
_next_id = 0
def __init__(self, value):
self.value = value
self.id = type(self)._next_id
type(self)._next_id += 1
def instance(self, value):
return type(self)._instances[value]
cls = type(classname, (EnumType, ), {})
instances = dict((value, cls(value)) for value in values)
cls._instances = instances
def __new__(cls, value):
raise TypeError('No more instances allowed')
cls.__new__ = staticmethod(__new__)
return cls
Genre = enum('Genre', ['scifi', 'comic', 'science'])
for item in Genre:
print item, item.value, item.id
assert(item is Genre(item.value))
assert(item is item.instance(item.value))
Genre('romance')
老答案
回應(yīng)你對(duì)Noctis Skytower答案的評(píng)論,其中你說(shuō)你想要Genre.comic =流派(‘漫畫(huà)’)(未經(jīng)測(cè)試):
class Genre(GenreBase):
genres = ['comic', 'scifi', ... ]
def __getattr__(self, attr):
if attr in type(self).genres:
self.__dict__[attr] = type(self)(attr)
return self.__dict__[attr]
這將創(chuàng)建一個(gè)類(lèi)型實(shí)例,以響應(yīng)嘗試訪問(wèn)它并將其附加到請(qǐng)求它的實(shí)例.如果您希望將它附加到整個(gè)類(lèi),請(qǐng)?zhí)鎿Q該行
self.__dict__[attr] == type(self)(attr)
同
type(self).__dict__[attr] = type(self)(attr)
這使得所有子類(lèi)都創(chuàng)建子類(lèi)的實(shí)例以響應(yīng)請(qǐng)求.如果您希望子類(lèi)創(chuàng)建Genre的實(shí)例,請(qǐng)將type(self)(attr)替換為Genre(attr)
標(biāo)簽:python,enumeration,sqlalchemy
總結(jié)
以上是生活随笔為你收集整理的python枚举类的意义_用于ORM目的的python枚举类的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 人行分提额什么意思
- 下一篇: 建设政务大数据有什么实际意义?目前有成熟