2013-04-30 88 views
7

我想在python中編寫一個「枚舉類」。我目前遇到的一個小麻煩是無法在枚舉類中定義枚舉值。也就是說,我可以這樣做:Python 2.x - 在同一類中創建類的靜態實例

class Fruit: 
    def __init__(self, name): 
     self.name = name 

class Fruits(Enum): 
    Apple = Fruit("apple") 

但我想這樣做,或者類似的清晰等價的:

class Fruit(Enum): 
    def __init__(self, name): 
     self.name = name 

    Apple = Fruit("apple") 

不幸的是,我收到以下錯誤: 名「果」未定義

這種情況下的可見性規則是什麼?是否有任何鮮爲人知的Python技巧可以幫助我?我更喜歡在Enum的元類中寫入可能的東西,因爲這會使用戶使用起來不那麼麻煩。

+1

,枚舉元類沒有顯示,因爲我認爲這是相當無關。 – Liosan 2013-04-30 11:08:14

+0

這是因爲'class'沒有完成定義,直到到達塊的末尾 – jamylak 2013-04-30 11:16:03

+1

在類定義之後,您可以執行一個'Fruit.Apple = Fruit(「apple」)'來創建一個實例並將其作爲class屬性。 – martineau 2013-04-30 11:21:27

回答

1

你可以做一個元類是做了一些簡單的像這樣:

class MetaEnum(type): 
    def __new__(cls, class_name, parents, attrs): 
     def __init__(self, name=None): 
      if name is not None: self.name = name 
     attrs['__init__'] = __init__ 
     Klass = type.__new__(cls, class_name, parents, attrs) 
     if 'instances' in attrs: 
      for name in attrs['instances']: 
       setattr(Klass, name.capitalize(), Klass(name)) 
      del Klass.instances # clean up 
     return Klass 

class Fruit(object): 
    __metaclass__ = MetaEnum 
    instances = ('apple', 'banana', 'cranberry') 

for attr_name in dir(Fruit): 
    if not attr_name.startswith('_'): 
     attr = getattr(Fruit, attr_name) 
     if type(attr) is Fruit: 
      print('Fruit.{}, is a Fruit named {}'.format(attr_name, getattr(attr, 'name'))) 
     else: 
      print('Fruit.{}, is a {}'.format(attr, type(attr))) 

輸出:

Fruit.Apple, is a Fruit named apple 
Fruit.Banana, is a Fruit named banana 
Fruit.Cranberry, is a Fruit named cranberry 
+0

不錯,如果我正確讀它,它做我想要的。我沒有想到這條路線。可惜的語法,我會努力一點...絕對+1。 – Liosan 2013-04-30 11:47:03

+0

你想要實例嗎?好的,請參閱我更新後的問題答案。 – martineau 2013-04-30 12:03:07

+0

Re:語法,如果你在全局模塊級定義了__metaclass__ = MetaEnum,它將成爲默認值,並且適用於任何遵循它的類定義(不指定它們自己)。 – martineau 2013-04-30 12:57:31

相關問題