自从我了解
以来,我就知道python以不同的方式对待此名称空间def foo(l=[]):
l.append(1)
print(l)
foo()
foo()
foo([])
foo()
将显示以下内容。
[1]
[1,1]
[1]
[1,1,1]
因此,我对它们用作对象初始化器表示怀疑。 然后最近我遇到了另一个类似的奇怪行为, 如下所示。
class Foo:
bar = 0
def __init__(self):
self.a = bar
Foo()
由于未在此命名空间中定义bar
,因此引发了异常。
class Foo:
bar = 0
def __init__(self, a=bar)
self.a = a
Foo()
现在,这成功地将由类变量foo
持有的值分配给初始化程序内的对象a
。
为什么会发生这些情况,以及如何处理默认参数值?
答案 0 :(得分:4)
三个事实:
def
类似的行为,可能会感到惊讶。第3点是最微妙的,也许与最初的预期相反。它记录在execution model中( 4.2.2。名称解析部分):
在类块中定义的名称范围仅限于该类块;它不会扩展到方法的代码块
这就是为什么在第二个示例中名称bar
不能解析的原因:
class Foo:
bar = 0
def __init__(self):
self.a = bar # name "bar" isn't accessible here, but code is valid syntax
Foo() # NameError: name 'bar' is not defined
请注意,bar
值0
仍可通过Foo.bar
或self.bar
作为类属性从方法内访问。
您现在应该了解为什么最后一个示例 起作用了:
class Foo:
bar = 0
def __init__(self, a=bar):
self.a = a
Foo()
考虑到上面的1-3点,您还应该能够正确预测此处发生的情况:
class Foo:
def __init__(self, a=bar):
self.a = a
bar = 0
Foo()
UnboundLocalError: local variable referenced before assignment why LEGB Rule not applied in this case中提供了有关怪异类范围的更多信息。