Python 按值将列表传递给函数

Python 按值将列表传递给函数,python,pass-by-value,Python,Pass By Value,我想通过值将列表传递到函数中。 默认情况下,列表和其他复杂对象通过引用传递给函数。 以下是一些决定: def add_at_rank(ad, rank): result_ = copy.copy(ad) .. do something with result_ return result_ 这个可以写得更短吗? 换句话说,我不想更改ad您可以使用[:],但对于包含列表(或其他可变对象)的列表,您应该选择copy.deepcopy(): lis[:]相当于list(lis

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

def add_at_rank(ad, rank):
    result_ = copy.copy(ad)
    .. do something with result_
    return result_
这个可以写得更短吗?
换句话说,我不想更改ad

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


浅拷贝通常足够好,而且可能比深拷贝快

如果对
结果所做的修改没有改变它所包含的项/属性,则可以利用这一点

举个简单的例子,如果你有一个棋盘

board = [[' ']*8 for x in range(8)]
你可以做一个浅显的副本

board2 = copy.copy(board)
可以安全地从
board2
添加/插入/弹出/删除/替换项目,但不能添加/插入/弹出/删除/替换其中包含的列表。如果要修改其中一个连续列表,必须创建一个新列表并替换现有列表

row = list(board2[2])
row[3] = 'K'
board2[2] = row

这需要更多的工作,但在时间和存储方面效率更高

这可能是装饰器函数的一个有趣的用例。大概是这样的:

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\u by\u value
将函数
f
作为输入,并创建一个新函数
\u 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'}"
如果是ad is列表,您可以简单地调用函数
add_at_rank(ad+[],rank)

这将在每次调用函数时创建list的新实例,该值等于ad


纯pythonic:)

如果
ad
是一个列表,你可以做
result\uuu=ad[:]
它不能写得更短,不。你必须显式复制列表。您可以在函数外部或函数内部执行此操作,但必须执行此操作。实际上,引用是通过值传递的。Python中不经常使用术语“by value”和“by reference”,因为它们往往会误导来自其他语言的人。正如@gnibbler所说,Python中的所有内容都是按值传递的,但有些值是引用。:)同样,处理这个问题的惯常方法是首先避免变异
结果
;通过转换旧列表(例如,使用列表理解、
映射、
过滤器等)创建新的
列表。有时这是不合适的,在不知道您的“.dosomething with result_u”代码看起来像什么或是做什么的情况下,不可能判断这是否正确。但它比Python新手(特别是Java或C++等语言的新手)所期望的更合适。另外,最好用
@functools.wrapps(f)
"inside function [1, 2, 3, 4] {1: 'foo', 3: 'bar'}"
"outside function [1, 2, 3] {1: 'foo'}"
>>>ad == ad + []
True

>>>ad is ad +[]
False