我不确定这是否是我对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
Run Code Online (Sandbox Code Playgroud)
我希望在bar2构造时,它的mylist实例变量将被设置为空列表.但是,当我在Python 2.6.6中运行此程序时,我得到以下输出:
Foo1: []
Foo2: []
Bar: []
Foo1: [4]
Foo2: [4]
Bar: [4]
bar2's list: [4]
Run Code Online (Sandbox Code Playgroud)
看起来Foo的mylist实例变量被保存在Bar类的多个实例中,但我不知道为什么会这样.你们可以给我的任何帮助将不胜感激.
问题是默认参数在模块初始化时绑定,而不是在函数调用时绑定,因此只有一个默认列表作为该函数的所有调用的默认值共享.
你真正想做的是:
def __init__(self, l=None):
if l is None:
l = []
self.mylist = l
Run Code Online (Sandbox Code Playgroud)
查阅有关默认参数值的 Python 教程\n它说:
\n\n\n\n\n重要警告:默认值仅计算一次。当默认值是可变对象(例如列表、字典或大多数类的实例)时,这会产生影响。
\n
或者例如,以下函数会累积在后续调用中传递给它的参数:
\n\ndef f(a, L=[]):\n L.append(a)\n return L\n\nprint f(1)\nprint f(2)\nprint f(3)\nRun Code Online (Sandbox Code Playgroud)\n\n这将打印
\n\n[1]\n[1, 2]\n[1, 2, 3]Run Code Online (Sandbox Code Playgroud)\n\n如果您不希望在后续调用之间共享默认值,您可以像这样编写函数:
\n\ndef f(a, L=None):\n if L is None:\n L = []\n L.append(a)\n return LRun Code Online (Sandbox Code Playgroud)\n