3

我有以下代码

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)方法来做这样的事情。

4

3 回答 3

11

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

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

会成功的。该PHONE名称在命名空间中可用,该命名空间将在语句完成执行Transcription成为类。class

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

该声明

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没有意义。

于 2011-01-11T08:52:24.327 回答
2

The class is not associated with its name until the end of the definition.

The way I would write this (and I can't guarantee that it's Pythonic) is:

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

Alternatively, setting PHONE to zero instead of WORD will be fine. The if statement will work regardless of the values of the constants, but the or will replace a zero value with PHONE.

Other options are to define the constants in another class or to bind the align_transcription method outside of the class:

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
于 2011-01-11T08:58:39.503 回答
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
于 2011-01-11T08:57:04.433 回答