了解python中实例属性的名称空间

时间:2019-02-22 15:23:54

标签: python

有时我可能会对术语感到困惑,但是我想我知道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,具有相同的行为。

1 个答案:

答案 0 :(得分:4)

foobar3()中,您要分配全局x变量的barob属性。您未在声明。 Python无法使用barob.x定义变量,因为它需要barob的现有实例来确定将x的值放在哪里。因此,它首先要查找实例(并查找全局实例),而不是声明变量。

如果您首先允许Python声明一个barob变量,然后为其分配变量,那就会有所不同:

barob = Bar(5)
def foobar3():
    barob   = Bar(0)
    barob.x = 7