2010-09-01 89 views
0

我正在使用定義各種方法的基類實現枚舉。實際的枚舉是它的子類,沒有附加的方法或屬性。 (每個子類都使用基類中定義的構造函數填充自己的值)。我使用了一個註冊表(一個存儲該類的所有實例的類屬性)。理想情況下,我想避免在每個子類中定義它。不幸的是,如果我在基類中定義它,所有的子類將最終共享相同的註冊表。python:在基類中定義註冊表

這裏有什麼好方法?

下面是實施情況,以幫助它(它基於@jchl評論python enumeration class for ORM purposes)。

class IterRegistry(type): 
    def __iter__(cls): 
     return iter(cls._registry.values()) 

class EnumType(metaclass = IterRegistry): 
    _registry = {} 
    _frozen = False 
    def __init__(self, token): 
     if hasattr(self, 'token'): 
      return 
     self.token = token 
     self.id = len(type(self)._registry) 
     type(self)._registry[token] = self 

    def __new__(cls, token): 
     if token in cls._registry: 
      return cls._registry[token] 
     else: 
      if cls._frozen: 
       raise TypeError('No more instances allowed') 
      else: 
       return object.__new__(cls) 

    @classmethod 
    def freeze(cls): 
     cls._frozen = True 

    def __repr__(self): 
     return self.token 

    @classmethod 
    def instance(cls, token): 
     return cls._registry[token] 

class Enum1(EnumType): pass 
Enum1('a') 
Enum1('b') 
for i in Enum1: 
    print(i) 

# not going to work properly because _registry is shared 
class Enum2(EnumType): pass 

回答

3

因爲你已經有了一個元類,所以你可以用它來自動添加一個單獨的_registry屬性給每個子類。

class IterRegistry(type): 
    def __new__(cls, name, bases, attr): 
     attr['_registry'] = {} # now every class has it's own _registry 
     return type.__new__(cls, name, bases, attr) 
0

如果你分享了註冊表,但每類分登記處相同,即

if cls.__name__ not in self._registry: 
    self._registry[cls.__name__] = {} 
self._registry[cls.__name__][token] = cls 

你居然甚至不需要cls.__name__,你應該能夠使用cls本身作爲關鍵。

+0

是的,這將工作。只是覺得我會向課堂揭露一些不必要的信息:理想情況下,我希望cls只知道自己的實例... – max 2010-09-02 10:36:53