Python命名空间(2.7和3)的意外行为

时间:2013-01-15 09:46:43

标签: python

  

可能重复:
  “Least Astonishment” in Python: The Mutable Default Argument

我只是想检查我期望这种方式工作的方式是否正确。这是我正在编写的类的简化版本:

class Foo(object):
     def __init__(self):
         pass
     def bar(self, test1=[], test2=[]):
         if test2:
             test1.append(1)
         print test1

现在,对我来说,test1和test2 - 除非设置 - 在调用功能栏时应始终设置为空列表。这意味着当打印test1时,列表中应该只有一个项目(假设您只提供一个项目作为参数)。但事实并非如此:

>>> i = Foo()
>>> i.bar()
[]
>>> i.bar(test2=[1])
[1]
>>> i.bar()
[1, 1]
>>> i.bar(test2=[1])
[1, 1, 1]

在这种情况下,你期望使用整数得到类似的结果:

class Foo(object):
     def __init__(self):
         pass
     def bar(self, test1=0, test2=0):
         if test2:
             test1 += 1
         print test1

但是在这里,test1始终设置为0:

>>> i = Foo()
>>> i.bar()
0
>>> i.bar(test2=1)
1
>>> i.bar(test2=1)
1
>>> i.bar(test2=1)
1

似乎列表在函数或类的命名空间中是持久的,但整数不是。

这可能是我的误解,所以我想澄清一下。

1 个答案:

答案 0 :(得分:1)

当声明函数时,函数的默认参数设置为,而不是每次调用函数时都设置。因此,声明函数时生成的列表只进行一次,并在每次调用函数时引用。另请参阅this question

因为列表是可变的,所以当您更改它们时,引用它的任何内容也会发生变化。但是整数是不可变(它们无法更改),因此当您将变量重新分配给另一个整数时,只会更改该变量,因为它引用了一个不同的对象。