如何每次都创建一个新的默认参数列表

时间:2013-08-01 10:27:48

标签: python default

我有以下设置:

def returnList(arg=["abc"]):
    return arg

list1 = returnList()
list2 = returnList()

list2.append("def")

print("list1: " + " ".join(list1) + "\n" + "list2: " + " ".join(list2) + "\n")

print(id(list1))
print(id(list2))

输出:

list1: abc def
list2: abc def

140218365917160
140218365917160

我可以看到arg = [“abc”]返回相同默认列表的副本,而不是每次都创建一个新列表。

我尝试过做

def returnList(arg=["abc"][:]):

def returnList(arg=list(["abc"])):

是否可以获取新列表,或者每次我想要某种默认值时,是否必须在方法中复制列表?

2 个答案:

答案 0 :(得分:5)

我见过的最好的模式就是

def returnList(arg=None):
    if arg is None: arg = ["abc"]
    ...

唯一可能的问题是,如果您希望None在此处成为有效输入,在这种情况下,您将不得不使用不同的哨兵值。

您的方法存在的问题是arg的默认参数被评估一次。复制操作符的作用并不重要,因为它只是评估而不是存储在函数中。在每次函数调用期间都不会重新评估它。

更新:

我不希望错过nneonneo的评论,使用新的object作为哨兵会很好地工作。

default = object()
def f(x = default):
    if x is default:
        ...

答案 1 :(得分:1)

您想要的是您自己陈述的内容:您每次都需要新的值副本。简单地调用函数不会自动执行任何操作,因此无法通过语法技巧完成此操作。但是你可以使用装饰器来做你想做的事情:

import copy

def keepDefaults(f):
  defaults = f.func_defaults
  def wrapped(*args, **kwargs):
    f.func_defaults = copy.deepcopy(defaults)
    return f(*args, **kwargs)
  return wrapped

@keepDefaults
def f(a=[1]):
  return a

f()[0].append(2)
print f()  # will print "[1]" instead of "[1, 2]"