有时我可能会对术语感到困惑,但是我想我知道python命名空间和范围规则以及global
关键字的使用。我知道从本地作用域(例如,在函数内部),除非声明了变量global
,否则我可以以只读模式访问全局作用域。
但是上课时,我发现有些奇怪的地方。我希望这个例子足够清楚:
class Bar:
def __init__(self, x):
self.x = x
barob = Bar(6)
def foobar():
barob = Bar(3) #local scope, the barob in global namespace is not affected.
foobar()
print(barob.x) #prints 6
def foobar2():
global barob #barob is the one in global space
barob = Bar(3)
foobar2()
print(barob.x) #prints 3
到目前为止,一切对我来说都是清楚的。但是如果我这样做:
barob = Bar(5)
def foobar3():
barob.x = 7
foobar3()
print(barob.x) #prints 7. Why?
所以我的问题是:为什么允许从x
的本地范围重新分配全局命名空间中的barob
的{{1}}属性?
当我在全局命名空间中写入变量(在这种情况下,是对象的属性)时,我会期望引发foobar3()
或解释器发出其他某种抱怨。
据我所知,最好的是,在涉及范围时,属性与变量的处理方式有所不同,但我不明白为什么。
如果相关,我正在使用python3.6.7,但我也尝试了python2.7,具有相同的行为。
答案 0 :(得分:4)
在foobar3()
中,您要分配全局x
变量的barob
属性。您未在声明。 Python无法使用barob.x
定义变量,因为它需要barob的现有实例来确定将x
的值放在哪里。因此,它首先要查找实例(并查找全局实例),而不是声明变量。
如果您首先允许Python声明一个barob
变量,然后为其分配变量,那就会有所不同:
barob = Bar(5)
def foobar3():
barob = Bar(0)
barob.x = 7