Python中类型之间的差异及其可见性

时间:2013-11-18 15:39:23

标签: python function exception types

我只是想知道,接下来的两个函数(Python 3.x)之间有什么区别

def first_example ():
    counter = 0
    def inc_counter ():
        counter += 1
    for i in range (10):
            inc_counter ()

def second_example ():
    counter = [0]
    def inc_counter ():
        counter[0] += 1
    for i in range (10):
            inc_counter ()

在赋值之前引用的第一个函数抛出异常,但第二个函数运行良好。有人可以解释一下,为什么python会记住数组,而不是整数?

4 个答案:

答案 0 :(得分:5)

您将在第一个嵌套函数中分配counter名称,使其成为局部变量。

在第二个示例中,您永远不会直接分配给counter,使其成为自由变量,编译器正确连接到父函数中的counter。你永远不会重新绑定名称,你只是改变了counter所指的列表。

使用nonlocal关键字将counter标记为自由变量:

def first_example ():
    counter = 0
    def inc_counter ():
        nonlocal counter
        counter += 1
    for i in range (10):
        inc_counter()

答案 1 :(得分:3)

除非您明确标记globalnonlocal,否则无法将内部函数(也称为“闭包”)捕获的变量分配给它。

在第一个示例中,由于您尝试分配,因此counter用于引用内部局部变量,而不是外部变量。在赋值之前引用此内部变量,这是一个错误。

在第二个示例中,您没有分配给变量,而是在其上调用__getitem__来执行索引查找。所以没关系,counter指的是外部变量。

答案 2 :(得分:1)

在第一个示例中,您的目的是将counter更改为指向另一个对象(整数1,因为它从0开始)。

在第二个示例中,counter仍然指向同一个对象:列表。列表的元素已更改。没有counter的任务分配。

如果没有(在Python 3中)声明counter非本地,则第一个是不允许的。在Python 2中,在任何情况下都不允许这样做。赋值+=使counter成为内部函数的局部变量。由于尚未在该范围内为其分配值,因此尝试使用它(如+= )会导致Python抱怨。

答案 3 :(得分:1)

在Python中,第一次在函数中分配变量时会创建变量。在您的第一个示例中,counterinc_counter内分配,自编写

counter += 1

就像写作

counter = counter + 1

因此在该范围内创建了一个名为counter的新变量。

在第二个示例中,您只访问计数器变量,而不是分配它,因此不会创建新变量。