为什么我不能在python中访问这个类成员?

时间:2011-01-11 08:49:21

标签: python class-members

我有以下代码

class Transcription(object):
    WORD = 0
    PHONE = 1
    STATE = 2

    def __init__(self):
        self.transcriptions = []

    def align_transcription(self,model,target=Transcription.PHONE):
        pass

这里的重要部分是我希望将一个类成员作为变量的默认值。但是,这会产生以下错误:

NameError: name 'Transcription' is not defined

为什么这不可能,以及做这样的事情的正确(pythonic)方法是什么。

3 个答案:

答案 0 :(得分:11)

您无法访问它,因为在Transcription语句运行时未定义def

 def align_transcription(self,model,target=PHONE):
        pass

会做到这一点。 PHONE名称在命名空间中可用,在<{em> Transcription语句完成执行后将成为class

这种方式的工作方式是class实际运行的语句。当Python遇到一个类语句时,它进入一个新的本地作用域并执行在class语句下缩进的所有内容,就像它是一个函数一样。然后,它会将生成的命名空间,类的名称和基类的元组传递给元类,默认情况下为type。元类返回自身的实例,它是实际的类。 def语句执行时,没有发生过这种情况。

声明

class Foo(object):
    a = 1
    def foo(self):
        print self.a

创建名称空间ns = {'a': 1, 'foo': foo},然后执行

Foo = type('Foo', (object,), ns)

这相当于

def foo(self):
    print self.a

Foo = type('Foo', (object,), {'a': 1, 'foo': foo})

您可以清楚地看到Foo在定义foo时未定义,因此Foo.a毫无意义。

答案 1 :(得分:2)

在定义结束之前,该类与其名称无关。

我写这个的方式(我不能保证它是Pythonic)是:

class Transcription(object):
    WORD = 1   # zero won't work below... need to change the value
    PHONE = 2
    STATE = 3

    def align_transcription(self, model, target=None):
        target = target or Transcription.PHONE
        # or
        if target is None: target = Transcription.PHONE

或者,将PHONE设置为零而不是WORD也可以。无论常量值如何,if语句都会起作用,但or将使用PHONE替换零值。

其他选项是在另一个类中定义常量或在类外部绑定align_transcription方法:

class Transcription(object):
    WORD = 0
    PHONE = 1
    STATE = 2

def _unbound_align_transcription(self, model, target=Transcription.PHONE):
    pass

Transcription.align_transcription = _unbound_align_transcription

答案 2 :(得分:1)

当您定义align_transcription方法时,Transaction类仍然不存在,但范围中有PHONE。 所以,你可以这样做:

class Transcription(object):
    WORD = 0
    PHONE = 1
    STATE = 2

def __init__(self):
    self.transcriptions = []

def align_transcription(self,model,target=PHONE):
    pass
如果您计划在子类或实例中覆盖PHONE,则

或使用target = None默认值:

def align_transcription(self,model,target=None):
    if target is None:
        target = self.PHONE