传递列表按值运行

时间:2013-03-13 04:24:22

标签: python pass-by-value

我想通过值将列表传递给函数。 默认情况下,列表和其他复杂对象通过引用传递给函数。 这是一些决定:

def add_at_rank(ad, rank):
    result_ = copy.copy(ad)
    .. do something with result_
    return result_

这可以写得更短吗? 换句话说,我不想改变广告

4 个答案:

答案 0 :(得分:10)

您可以使用[:],但对于包含列表(或其他可变对象)的列表,您应该使用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

答案 1 :(得分:2)

这可能是装饰器功能的一个有趣的用例。像这样:

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。< / p>

用法:

@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'}"

答案 2 :(得分: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

这是一项更多的工作,但在时间和存储方面更有效率

答案 3 :(得分:0)

如果 ad list ,您可以简单地将您的功能称为add_at_rank(ad + [], rank)

每次调用函数时都会创建 list 的新实例,该值与 ad 相当。

>>>ad == ad + []
True

>>>ad is ad +[]
False

纯pythonic:)