我有以下代码
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)方法是什么。
答案 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