对象可变性对python中的作用域有什么影响?

对象可变性对python中的作用域有什么影响?,python,scope,closures,Python,Scope,Closures,以下荒谬但具有说明性的代码通过修改封闭函数中定义的列表而正常工作: def outside1(): l = list('abcd') def inside(a): print "Before - %i: %r" % (id(l), l) l.append(a) print "After - %i: %r\n" % (id(l), l) return inside f = outside1() [f(c) for c in

以下荒谬但具有说明性的代码通过修改封闭函数中定义的列表而正常工作:

def outside1():
    l = list('abcd')
    def inside(a):
        print "Before - %i: %r" % (id(l), l)
        l.append(a)
        print "After - %i: %r\n" % (id(l), l)
    return inside

f = outside1()
[f(c) for c in 'efgh']
此代码还可以显示在封闭范围内定义的不可变项在封闭范围内是可访问的:

def outside2():
    t = tuple('abcd')
    def inside():
        print "%i: %r" % (id(t), t)
    return inside

outside2()()
但是,如果在赋值之前引用了局部变量“t”,则此操作将失败:


有人能解释一下这是怎么回事吗?我的第一个猜测是,我可以变异,但不能分配给封闭范围,但考虑到outside2可以工作,我至少希望打印前语句可以工作。

易变性对范围没有影响


问题是分配给不在当前范围内的变量会创建该变量,而仅仅读取该变量不会创建该变量。

可变性对范围没有影响


问题是,分配给不在当前作用域中的变量会创建该变量,而仅仅读取该变量不会创建该变量。

Python在编译时静态地检测名称的作用域:分配给函数内部的名称会成为该函数的局部名称。那么这条线呢

t = t + (a,)
将t局部渲染为inside,任何对t inside的查找都将尝试查找inside的局部变量。当超过上述行时,t还不存在,因此存在误差

在Python3.x中,可以通过显式地将t声明为非本地来解决该问题:


所有这些都与易变性完全无关。使用列表的示例不会重新分配名称l,而使用元组的示例会重新分配名称t;这是重要的区别,而不是易变性。

Python在编译时静态地检测名称的范围:分配给函数内部的名称成为该函数的本地名称。那么这条线呢

t = t + (a,)
将t局部渲染为inside,任何对t inside的查找都将尝试查找inside的局部变量。当超过上述行时,t还不存在,因此存在误差

在Python3.x中,可以通过显式地将t声明为非本地来解决该问题:


所有这些都与易变性完全无关。使用列表的示例不会重新分配名称l,而使用元组的示例会重新分配名称t;这是重要的区别,而不是易变性。

Marcin是对的。易变性对范围绝对没有影响

您需要了解的是,在第一个示例中,当您对l指向的列表进行变异时,您只需读取变量l,然后对其调用一些方法。append。这与第二个示例中读取变量t的情况完全相同

在这两种情况下,您都没有在外部范围内赋值给变量,只是读取它。易变性只是意味着您可以更改变量指向的内容,从而以这种方式共享更改。但从变量和范围来看,绝对没有区别

在第三个示例中,您正在为变量t赋值。这就是区别。Python2.x除了通过全局变量分配全局变量外,没有办法分配给外部变量。Python3.x具有非本地特性,允许您这样做。请注意,可变性与此无关:如果在第一个示例中尝试将变量l指向的对象赋值,而不是仅对其进行变异,则会遇到相同的问题:

def outside1():
    l = list('abcd')
    def inside(a):
        print "Before - %i: %r" % (id(l), l)
        l = [1,2,3]
        print "After - %i: %r\n" % (id(l), l)
    return inside

马辛是对的。易变性对范围绝对没有影响

您需要了解的是,在第一个示例中,当您对l指向的列表进行变异时,您只需读取变量l,然后对其调用一些方法。append。这与第二个示例中读取变量t的情况完全相同

在这两种情况下,您都没有在外部范围内赋值给变量,只是读取它。易变性只是意味着您可以更改变量指向的内容,从而以这种方式共享更改。但从变量和范围来看,绝对没有区别

在第三个示例中,您正在为变量t赋值。这就是区别。Python2.x除了通过全局变量分配全局变量外,没有办法分配给外部变量。Python3.x具有非本地特性,允许您这样做。请注意,可变性与此无关:如果在第一个示例中尝试将变量l指向的对象赋值,而不是仅对其进行变异,则会遇到相同的问题:

def outside1():
    l = list('abcd')
    def inside(a):
        print "Before - %i: %r" % (id(l), l)
        l = [1,2,3]
        print "After - %i: %r\n" % (id(l), l)
    return inside

Python在编译时静态地检测名称的范围,谢谢,这是简单的答案;py3k技巧是一个很好的奖励。Python在编译时静态地检测名称的范围,谢谢,这是简短的答案;py3k提示是一个不错的奖励。