有时,默认参数为空列表似乎很自然。然而,Python在这些情况下会产生意想不到的行为。

例如,我有一个函数:

def my_func(working_list=[]):
    working_list.append("a")
    print(working_list)

第一次调用它时,默认值将工作,但之后的调用将更新现有列表(每次调用一个“a”)并打印更新后的版本。

那么,python的方法是什么来获得我想要的行为(每次调用都有一个新的列表)?


当前回答

在这种情况下,这并不重要,但你可以使用对象标识来测试None:

if working_list is None: working_list = []

你也可以利用python中布尔运算符or的定义:

working_list = working_list or []

但是,如果调用者给你一个空列表(算作false)作为working_list,并期望你的函数修改他给它的列表,这将出乎意料。

其他回答

也许最简单的事情就是在脚本中创建列表或元组的副本。这样就避免了检查的需要。例如,

    def my_funct(params, lst = []):
        liste = lst.copy()
         . . 

其他答案已经提供了要求的直接解决方案,然而,由于这是Python程序员新手的一个非常常见的陷阱,因此值得添加对Python为什么会这样做的解释,这在可变默认参数下的Python漫游指南中得到了很好的总结:

Python的默认实参在定义函数时只计算一次,而不是每次调用函数时都计算(就像Ruby中那样)。这意味着如果你使用一个可变的默认参数并改变了它,你将在以后所有对函数的调用中也改变了这个对象。

我参加了UCSC的编程扩展课程Python

这是真的:def Fn(data = []):

A)是一个好主意,这样你的数据列表在每次调用时都是空的。 B)是一个好主意,这样所有不提供任何参数的函数调用都将获得空列表作为数据。 C)是一个合理的想法,只要你的数据是一个字符串列表。 D)是一个坏主意,因为默认的[]会积累数据,并且默认的[]会随着后续的调用而改变。

答:

D)是一个坏主意,因为默认的[]会积累数据,并且默认的[]会随着后续的调用而改变。

我可能跑题了,但请记住,如果你只是想传递一个可变数量的参数,python的方法是传递一个元组*args或一个字典**kargs。这些是可选的,比语法myFunc([1,2,3])更好。

如果你想传递一个元组:

def myFunc(arg1, *args):
  print args
  w = []
  w += args
  print w
>>>myFunc(1, 2, 3, 4, 5, 6, 7)
(2, 3, 4, 5, 6, 7)
[2, 3, 4, 5, 6, 7]

如果你想传递一个字典:

def myFunc(arg1, **kargs):
   print kargs
>>>myFunc(1, option1=2, option2=3)
{'option2' : 2, 'option1' : 3}

在这种情况下,这并不重要,但你可以使用对象标识来测试None:

if working_list is None: working_list = []

你也可以利用python中布尔运算符or的定义:

working_list = working_list or []

但是,如果调用者给你一个空列表(算作false)作为working_list,并期望你的函数修改他给它的列表,这将出乎意料。