我想按值将列表传递给函数。默认情况下,列表和其他复杂对象通过引用传递给函数。这是一个愿望:
def add_at_rank(ad, rank):
result_ = copy.copy(ad)
.. do something with result_
return result_
这可以写得更短吗?换句话说,我不想改变ad。
我想按值将列表传递给函数。默认情况下,列表和其他复杂对象通过引用传递给函数。这是一个愿望:
def add_at_rank(ad, rank):
result_ = copy.copy(ad)
.. do something with result_
return result_
这可以写得更短吗?换句话说,我不想改变ad。
您可以使用[:]
,但对于包含列表(或其他可变对象)的列表,您应该使用copy.deepcopy()
:
lis[:]
等效于list(lis)
or copy.copy(lis)
,并返回列表的浅表副本。
In [33]: def func(lis):
print id(lis)
....:
In [34]: lis = [1,2,3]
In [35]: id(lis)
Out[35]: 158354604
In [36]: func(lis[:])
158065836
何时使用deepcopy()
:
In [41]: lis = [range(3), list('abc')]
In [42]: id(lis)
Out[42]: 158066124
In [44]: lis1=lis[:]
In [45]: id(lis1)
Out[45]: 158499244 # different than lis, but the inner lists are still same
In [46]: [id(x) for x in lis1] = =[id(y) for y in lis]
Out[46]: True
In [47]: lis2 = copy.deepcopy(lis)
In [48]: [id(x) for x in lis2] == [id(y) for y in lis]
Out[48]: False
这可能是装饰器功能的一个有趣用例。像这样的东西:
def pass_by_value(f):
def _f(*args, **kwargs):
args_copied = copy.deepcopy(args)
kwargs_copied = copy.deepcopy(kwargs)
return f(*args_copied, **kwargs_copied)
return _f
pass_by_value
将函数f
作为输入并创建一个新函数_f
,该函数深度复制其所有参数,然后将它们传递给原始函数f
。
用法:
@pass_by_value
def add_at_rank(ad, rank):
ad.append(4)
rank[3] = "bar"
print "inside function", ad, rank
a, r = [1,2,3], {1: "foo"}
add_at_rank(a, r)
print "outside function", a, r
输出:
"inside function [1, 2, 3, 4] {1: 'foo', 3: 'bar'}"
"outside function [1, 2, 3] {1: 'foo'}"
浅拷贝通常足够好,并且可能比深拷贝更快。
result_
如果您所做的修改没有改变它包含的项目/属性,您可以利用这一点。
举个简单的例子,如果你有一个棋盘
board = [[' ']*8 for x in range(8)]
你可以做一个浅拷贝
board2 = copy.copy(board)
从 中追加/插入/弹出/删除/替换项目是安全的board2
,但不是它包含的列表。如果要修改其中一个包含的列表,则必须创建一个新列表和replace
现有列表
row = list(board2[2])
row[3] = 'K'
board2[2] = row
工作量多一点,但时间和存储效率要高得多
如果广告是列表,您可以简单地将您的函数称为add_at_rank(ad + [], rank)
.
这将在您每次调用函数时创建新的list实例,该值相当于ad。
>>>ad == ad + []
True
>>>ad is ad +[]
False
纯pythonic :)