我有以下设置:
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"])):
是否可以获取新列表,或者每次我想要某种默认值时,是否必须在方法中复制列表?
答案 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]"