我为什么无法在Python中访问这个类成员?

3 投票
3 回答
538 浏览
提问于 2025-04-16 09:45

我有以下代码

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

为什么这样做不行呢?那有什么正确的(符合Python风格的)方法来实现类似的功能呢?

3 个回答

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
2

这个类在定义完成之前是和它的名字没有关联的。

我会这样写(虽然我不能保证这符合Python的风格):

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
11

你无法访问它,因为在执行 def 语句时,Transcription 还没有被定义。

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

这样做就可以了。PHONE 这个名字在命名空间中是可用的,而它会在 class 语句执行完后变成 Transcription 类。

这个过程是这样的: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 是没有意义的。

撰写回答