按值传递列表给函数
我想把一个列表传递给函数,但希望是按值传递。默认情况下,列表和其他复杂对象是按引用传递给函数的。也就是说,函数内部对这个列表的修改会影响到原来的列表。
def add_at_rank(ad, rank):
result_ = copy.copy(ad)
.. do something with result_
return result_
有没有更简洁的写法?换句话说,我希望不改变ad这个列表。
4 个回答
0
浅拷贝通常就足够用了,而且可能比深拷贝快很多。
如果你对 result_
的修改不涉及到它里面的项目或属性,那你可以利用这一点。
举个简单的例子,如果你有一个棋盘
board = [[' ']*8 for x in range(8)]
你可以做一个浅拷贝
board2 = copy.copy(board)
你可以安全地在 board2
上添加、插入、弹出、删除或替换项目,但不能直接修改它里面的列表。如果你想修改其中一个列表,你必须创建一个新列表,然后用 replace
来替换掉原来的列表。
row = list(board2[2])
row[3] = 'K'
board2[2] = row
这虽然多了一点工作,但在时间和存储上效率高得多。
7
这可能是一个有趣的装饰器函数的用法。像这样:
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'}"
21
你可以使用 [:]
来复制列表,但如果列表里面还有其他列表(或者其他可变对象),那就应该使用 copy.deepcopy()
。
lis[:]
相当于 list(lis)
或者 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