我不确定这是否是我对Python中OOP工作方式的基本误解,但我看到了一些非常奇怪的行为。这是一段代码:
class Foo(object):
def __init__(self, l = []):
print "Foo1:", l
self.mylist = l
print "Foo2:", self.mylist
class Bar(Foo):
def __init__(self, label=None):
self.label = label
super(Bar, self).__init__()
print "Bar:", self.mylist
bar1 = Bar()
bar1.mylist.append(4)
bar2 = Bar()
print "bar2's list:", bar2.mylist
我希望在构造bar2
时,其mylist
实例变量将被设置为空列表。但是,当我在Python 2.6.6中运行此程序时,我得到以下输出:
Foo1: []
Foo2: []
Bar: []
Foo1: [4]
Foo2: [4]
Bar: [4]
bar2's list: [4]
看起来Foo的mylist实例变量被保存在Bar类的多个实例中,但我不知道为什么会这样。我们非常感谢你们给予我的任何帮助。
答案 0 :(得分:6)
问题是默认参数在模块初始化时绑定,而不是在函数调用时绑定,因此只有一个默认列表作为该函数的所有调用的默认值共享。
你真正想做的是:
def __init__(self, l=None):
if l is None:
l = []
self.mylist = l
答案 1 :(得分:2)
在Python tutorial on default argument values抓一个战利品 它说:
重要警告:默认值仅评估一次。当默认值是可变对象(例如列表,字典或大多数类的实例)时,这会有所不同。
或者示例,以下函数累积在后续调用中传递给它的参数:
def f(a, L=[]):
L.append(a)
return L
print f(1)
print f(2)
print f(3)
这将打印
[1]
[1, 2]
[1, 2, 3]
如果您不希望在后续调用之间共享默认值,则可以编写如下函数:
def f(a, L=None):
if L is None:
L = []
L.append(a)
return L