2010-07-23 63 views
1

在Python中,我想要一个具有初始化值的类属性,一个字典。我写了这个代码:Python - 从类内部引用类名称

class MetaDataElement: 
    (MD_INVALID, MD_CATEGORY, MD_TAG) = range(3) 
    mapInitiator2Type = {'!':MetaDataElement.MD_CATEGORY, 
         '#':MetaDataElement.MD_TAG} 

但是当我尝试运行这段代码,我得到一个错误消息“NameError:名字‘MetaDataElement’没有定义”。你可以帮帮我吗?

在此先感谢。

回答

2

正在建设中,而它不能指MetaDataElement,因为它还不存在。因此,

class MetaDataElement: 
    (MD_INVALID, MD_CATEGORY, MD_TAG) = range(3) 
    mapInitiator2Type = {'!':MetaDataElement.MD_CATEGORY, 
         '#':MetaDataElement.MD_TAG} 

失败的原因为mapInitiator2Type非常需要建设到MetaDataElement有属性,它还不具备。你可以把你的常量MD_INVALID等看作是你的类的本地构造的变量。这就是为什么下面的作品,icktoofay写道:

class MetaDataElement: 
    (MD_INVALID, MD_CATEGORY, MD_TAG) = range(3) 
    mapInitiator2Type = {'!': MD_CATEGORY, # MD_CATEGORY is like a local variable! 
         '#': MD_TAG} 

但是,您可以参考类MetaDataElement任何尚未未解释的代码,如

def method_of_MetaDataElement(self): 
     print MetaDataElement.MD_TAG 

你甚至参考MetaDataElement,在这里,因为当执行method_of_MetaDataElement()MD_TAG不是一种局部变量(MD_TAG仅在类构造期间被定义为一种局部变量)。一旦类MetaDataElement创建,MD_TAG只是一个类属性,这就是为什么method_of_MetaDataElement()必须这样。

+0

最后一个例子可以用'self.MD_TAG'编写,它避免了引用类的任何需要名称。 – Marcin 2012-07-13 03:43:38

+0

@Marcin:'self.MD_TAG'也是一种可能性,但它不等同于'MetaDataElement.MD_TAG',如果MetaDataElement被子类化(子类可能会覆盖'MD_TAG')。两者都是有效的,但哪一个选择取决于当前的情况。 – EOL 2012-07-13 07:48:33

+0

老实说,我认为防止子类能够有效地改变类成员的方法可能是错误的,这就是为什么我会推荐使用'self',除非有特定的理由来阻止它。 – Marcin 2012-07-13 13:14:05

0

首先,您使用的是旧式类。您应该使用新式类,如下所示:

class MetaDataElement(object): 
    ... 

请注意(object)。无论如何,只要在引用类属性时删除MetaDataElement.即可。这是它会是什么时候这样做了,如:

class MetaDataElement(object): 
    (MD_INVALID, MD_CATEGORY, MD_TAG) = range(3) 
    mapInitiator2Type = {'!': MD_CATEGORY, 
         '#': MD_TAG} 
+0

也许redism是在Python 3中编写的,*是*使用新风格的类。 :) – EOL 2010-07-23 06:40:32

+0

@EOL:我没有意识到Python 3默认使用了新风格的类。这很好。 – icktoofay 2010-07-24 02:23:27

+0

以下是参考资料:“经典课不见了。” (http://docs.python.org/release/3.0.1/whatsnew/3.0.html#removed-syntax) – EOL 2010-07-24 10:30:44