Python中的局部、全局和全局对象
我有一个关于Python中的局部和全局变量以及全局对象的问题。请看以下代码:Python中的局部、全局和全局对象,python,Python,我有一个关于Python中的局部和全局变量以及全局对象的问题。请看以下代码: var = 0 class Test(): var = 0 test = Test() def sum(): Test.var += 1 test.var += 1 var += 1 sum() 如果我运行该代码,则仅在“var+=1”行触发异常。前面的两行可以工作。我阅读了Python常见问题解答。我认为函数的前两行没有例外,因为引用了“Test”和“Test”。分配了成员“
var = 0
class Test():
var = 0
test = Test()
def sum():
Test.var += 1
test.var += 1
var += 1
sum()
如果我运行该代码,则仅在“var+=1”行触发异常。前面的两行可以工作。我阅读了Python常见问题解答。我认为函数的前两行没有例外,因为引用了“Test”和“Test”。分配了成员“var”,但“Test”和“Test”是全局的,因为它们被引用以获取成员。常见问题解答说:“在Python中,仅在函数中引用的变量是隐式全局变量。如果在函数体的任何位置为变量赋值,则假定该变量为局部变量。”
所以,问题是。。。我的假设正确吗?看看这些函数:
def f():
var += 1
def g():
var = var.__iadd__(1)
g
是f
函数的字面版本(当然,Python在第一个版本中使用INPLACE\u ADD
操作码,而不查找\u iadd\u
属性)
但是,正如您所看到的,名称var
在这两个函数中加载一次并存储一次。所以,如果你分配了一个变量,就像FAQ所说的,除非你先声明它为全局变量,否则它是局部变量
那么,如何加载一个不存在的局部变量求和1
,然后用相同的名称再次存储
类属性之所以有效,是因为您正在执行以下操作:
Test.var = Test.var.__iadd__(1)
和
var
确实存在于Test
范围内(因此可以对其进行查找和重新分配)。查看以下功能:
def f():
var += 1
def g():
var = var.__iadd__(1)
g
是f
函数的字面版本(当然,Python在第一个版本中使用INPLACE\u ADD
操作码,而不查找\u iadd\u
属性)
但是,正如您所看到的,名称var
在这两个函数中加载一次并存储一次。所以,如果你分配了一个变量,就像FAQ所说的,除非你先声明它为全局变量,否则它是局部变量
那么,如何加载一个不存在的局部变量求和1
,然后用相同的名称再次存储
类属性之所以有效,是因为您正在执行以下操作:
Test.var = Test.var.__iadd__(1)
而
var
确实存在于Test
范围内(因此可以对其进行查找和重新分配)。本质上,这些规则是为了避免歧义:
var = 0 # a variable in the global namespace
class Test():
var = 0 # this is a attribute of the Test class
test = Test()
def sum():
Test.var += 1
test.var += 1 # these explicity mention on which object the name
# should be stored
blah = var # reads from a outer scope, but assigns to a local variable
var = Test # new local variable which shadows the outer name
# not great but understandable
var += 1 # this looks like it assigns to a local variable
# but since a name from a outer scope is read first,
# Python is not sure what the programmer really want to do
# (maybe assign to the outer scope, or first read it then shadow?)
# instead of guessing Python raises an exception,
# forcing the programmer to use `global` or a different name
本质上,这些规则是为了避免歧义:
var = 0 # a variable in the global namespace
class Test():
var = 0 # this is a attribute of the Test class
test = Test()
def sum():
Test.var += 1
test.var += 1 # these explicity mention on which object the name
# should be stored
blah = var # reads from a outer scope, but assigns to a local variable
var = Test # new local variable which shadows the outer name
# not great but understandable
var += 1 # this looks like it assigns to a local variable
# but since a name from a outer scope is read first,
# Python is not sure what the programmer really want to do
# (maybe assign to the outer scope, or first read it then shadow?)
# instead of guessing Python raises an exception,
# forcing the programmer to use `global` or a different name
我认为,报告的前两行也不例外
函数,因为“测试”和“测试”被引用
对。它们指的是类属性var
,而不是您定义的全局属性
分配了成员“var”,但“Test”和“Test”是全局的,因为它们被引用以获取成员
或者换句话说,Test
和Test
在全局名称空间中可用,因此Test.var
和Test.var
起作用
如果sum()
中未更改var
的值,则会得到0,因为上面的行更改了Test
class属性,而不是全局属性。在总和中添加一些print
s并删除var+=1
def sum():
Test.var += 1
print Test.var
test.var += 1
print test.var
print var
sum()
…给出:
1
2
0
但当我试图在sum函数中为var赋值时,我甚至在该行之前就得到了一个错误:
>>> def sum():
... Test.var += 1
... print Test.var
... test.var += 1
... print test.var
... print var
... var += 1
... print var
...
>>> sum()
1
2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in sum
UnboundLocalError: local variable 'var' referenced before assignment
输出:
1
2
0 # notice that global var is still 0 because the above var+=1 are for Test.var
1
编辑:关于我提到的“前瞻”行为。本打算发布一个关于它的问题,但在这个答案中解释得很好:(to) 我认为,报告的前两行也不例外 函数,因为“测试”和“测试”被引用 对。它们指的是类属性
var
,而不是您定义的全局属性
分配了成员“var”,但“Test”和“Test”是全局的,因为它们被引用以获取成员
或者换句话说,Test
和Test
在全局名称空间中可用,因此Test.var
和Test.var
起作用
如果sum()
中未更改var
的值,则会得到0,因为上面的行更改了Test
class属性,而不是全局属性。在总和中添加一些print
s并删除var+=1
def sum():
Test.var += 1
print Test.var
test.var += 1
print test.var
print var
sum()
…给出:
1
2
0
但当我试图在sum函数中为var赋值时,我甚至在该行之前就得到了一个错误:
>>> def sum():
... Test.var += 1
... print Test.var
... test.var += 1
... print test.var
... print var
... var += 1
... print var
...
>>> sum()
1
2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in sum
UnboundLocalError: local variable 'var' referenced before assignment
输出:
1
2
0 # notice that global var is still 0 because the above var+=1 are for Test.var
1
编辑:关于我提到的“前瞻”行为。本打算就此发表一个问题,但在这个答案中已得到很好的解释:(to)“避免歧义”在精神上是正确的,但最后一段关于
var+=1
如何出错的内容并不十分准确。Python永远无法将var+=1
解释为从全局变量读取,然后写入局部变量。如果global var
起作用,它可以读取和写入全局变量,否则它将同时读取和写入本地var
。如果此时还没有一个本地var
,那么您会得到一个关于尝试从一个不存在的变量中读取的异常。“避免歧义”在精神上是正确的,但最后一段对于var+=1
如何出错并不十分准确。Python永远无法将var+=1
解释为从全局变量读取,然后写入局部变量。如果global var
起作用,它可以读取和写入全局变量,否则它将同时读取和写入本地var
。如果此时还没有本地var
,那么您会遇到一个异常,即尝试从一个不存在的变量中读取。