我知道自从我发现python以来,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
。为什么会发生这些情况以及如何处理默认参数值?
三个事实:
def
。第三点是最微妙的,也许与最初的期望相反。它记录在执行模型中(第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
value0
用作类属性:通过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中有关于奇怪的类作用域的更多信息:赋值之前引用了局部变量,为什么在这种情况下不应用LEGB规则。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句