按值传递列表给函数

11 投票
4 回答
19179 浏览
提问于 2025-04-17 18:54

我想把一个列表传递给函数,但希望是按值传递。默认情况下,列表和其他复杂对象是按引用传递给函数的。也就是说,函数内部对这个列表的修改会影响到原来的列表。

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

撰写回答