为什么python能够从外部作用域读取'list'对象,但给出;作业前参考“;“int”对象出错?
我对这些代码感到困惑:为什么python能够从外部作用域读取'list'对象,但给出;作业前参考“;“int”对象出错?,python,python-2.7,Python,Python 2.7,我对这些代码感到困惑: def a(): count1=[0] count2=0 def b(): count1[0]=count1[0]+1 count2=count2+1 print count1,count2 b() count1作为一个列表发布,它运行良好,而b()中的count2将导致分配前引用的错误。为什么? 首先,您可以访问但不能修改超出当前范围的变量。如果您真的想这样做,您必须使用关键字非本地 其次
def a():
count1=[0]
count2=0
def b():
count1[0]=count1[0]+1
count2=count2+1
print count1,count2
b()
count1
作为一个列表发布,它运行良好,而b()中的count2
将导致分配前引用的错误。为什么? 首先,您可以访问但不能修改超出当前范围的变量。如果您真的想这样做,您必须使用关键字非本地
其次,count1
实际上是list对象实例的引用,所以如果不更改它引用的内容,它就不是对该变量的直接修改
第三,count2
是一个实值,更改它的值意味着直接修改这个变量
您可以通过用count1=list()替换count1[0]=count[0]+1
来测试这一点。它也会导致异常。因为b
分配给count2
,这会隐式创建count2
作为b
中的局部变量,而b
中对count2
的所有引用都会引用此局部变量。因此,在这一行:
count2 = count2 + 1
# ^^^^^^
您正在尝试读取尚未初始化的变量
count1
是不同的,因为b
只读取count1
;它从未分配给它:
count1[0] = ...
这将从count1
读取以获取包含的列表,然后修改第一个元素。在您的代码中count1
是列表的引用,使用count1[0]
尝试访问count1
列表的第0个索引。因此,当您这样做时:
count1[0] = count1[0]+1
count2 = count2 + 1
您正在访问在b()
函数外部定义的同一count1
对象
但是count2的情况并非如此。当您这样做时:
count1[0] = count1[0]+1
count2 = count2 + 1
您正在尝试创建一个新的count2
对象,在这种情况下b()
不会从外部范围读取count2
的值。为了从外部作用域访问count2
,可以使用关键字(从Python 3.x开始提供)。因此,您的代码应为:
# For Python 3.x
def a():
count2=0
def b():
nonlocal count2
# ^ used here
count2 = count2+1
b()
但由于您使用的是Python2.x,并且其中不提供非本地
,因此可以通过使用dict
将count2
变量存储为:
# Workaround for Python 2.x
def a():
nonlocal_dict = { # `dict` to store nonlocal variables
'count2': 0
}
def b():
nonlocal_dict['count2'] = nonlocal_dict['count2']+1
# ^ this `dict` will be available here
b()
请看一下:
您需要使用nonlocal关键字,因为在python中,变量follow LEGB rules意味着首先查找本地、封闭、全局和内置范围。这里您访问的是封闭变量,所以应该在变量前面使用非局部变量
def a():
count1=[0]
count2=0
def b():
nonlocal count2
count1[0]=count1[0]+1
count2=count2+1
print (count1,count2)
b()
a()
没有区别,但你和他们做了不同的事情。请尝试count1=[count1[0]+1]
。在这种情况下,变量不是global
。@MateenUlhaq my bad,应该是nonlocal
。