Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/327.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.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能够从外部作用域读取'list'对象,但给出;作业前参考“;“int”对象出错?_Python_Python 2.7 - Fatal编程技术网

为什么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