Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python中的局部、全局和全局对象_Python - Fatal编程技术网

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”。分配了成员“

我有一个关于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”,但“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
,那么您会遇到一个异常,即尝试从一个不存在的变量中读取。