题
我想模仿在python通按值行为。换句话说,我想绝对保证,我写不修改用户的功能提供的数据。
一种可能的方式是使用深拷贝:
from copy import deepcopy
def f(data):
data = deepcopy(data)
#do stuff
有更高效或多个 Python化的方法来实现这个目标,使得尽可能少的假设地了解正在传递的对象(如.clone()方法)
修改强>
我知道,在技术上一切都在Python是按值传递。我感兴趣的是的仿的行为,即确保我不惹传递给函数的数据。我想最一般的方法是克隆所讨论的对象或者与它自己的克隆机制或与deepcopy的。
解决方案
有是这样做的没有Python的方式。
Python提供很少设施的强制执行措施的的东西,如私人或只读数据。该Python的理念是“我们都同意的成人”:在这种情况下,这意味着“函数不应该改变的数据”是规范的一部分,但在代码没有得到执行。
如果你想使数据的副本,你可以得到的最接近的是你的解决方案。但是copy.deepcopy
,除了是低效率的,还具有警告如:
由于深拷贝拷贝一切可能复制太多,例如,应该甚至副本之间共享的管理的数据结构。
[...]
这个模块并不复制类型,如模块,方法,堆栈跟踪,堆栈帧,文件,插座,窗口,阵列或任何类似类型的。
所以我只是建议,如果你知道你正在处理的内置Python类型或您自己的对象(在这里您可以通过定义__copy__
/ __deepcopy__
特殊方法复制定制行为,没有必要来定义自己clone()
方法)。
其他提示
您可以做一个装饰,并把克隆行为这一点。
>>> def passbyval(func):
def new(*args):
cargs = [deepcopy(arg) for arg in args]
return func(*cargs)
return new
>>> @passbyval
def myfunc(a):
print a
>>> myfunc(20)
20
这是不是最可靠的方法,并且不处理键值参数或类的方法(缺乏自我的说法),但你得到的图片。
请注意,下面的语句是相等的:
@somedecorator
def func1(): pass
# ... same as ...
def func2(): pass
func2 = somedecorator(func2)
您甚至可以有装饰采取某种形式的函数,它的克隆,从而允许装饰的用户来决定克隆策略。在这种情况下,装饰可能最好为具有__call__
重写类实现。
有仅一对夫妇的工作作为参考,就像list
,例如内置typs的。
所以,对我做一通按值,对于列表中,在这个例子中,Python的方式,将是:
list1 = [0,1,2,3,4]
list2 = list1[:]
list1[:]
创建列表1的一个新实例,并且可以将其分配给一个新的变量。
也许你可以写,可以接受一个参数,然后检查其类型的函数,并根据该resulta,执行内置操作时可能会返回传入的参数的新实例。
正如我刚才所说,只有少数内建类型,他们的行为是类似的参考,列出了这个例子。
任何方式...希望它能帮助。
通常传递数据时的外部API,则可以通过将其作为不可变对象保证数据的完整性,例如包住数据转换成一个元组。这不能被修改,如果这是你试图阻止你的代码是什么。
我无法找出任何其他 Python化选项。但我个人更喜欢更加的 OO 的方式。
class TheData(object):
def clone(self): """return the cloned"""
def f(data):
#do stuff
def caller():
d = TheData()
f(d.clone())
虽然我敢肯定,有没有做到这一点真的Python的方式,我希望pickle
模块会给你你有任何业务处理的一切有价值的东西的副本。
import pickle
def f(data):
data = pickle.loads(pickle.dumps((data)))
#do stuff
继 user695800的的回答,通过值传递用于与所述列表可能[:]操作者
def listCopy(l):
l[1] = 5
for i in l:
print i
调用
In [12]: list1 = [1,2,3,4]
In [13]: listCopy(list1[:])
1
5
3
4
list1
Out[14]: [1, 2, 3, 4]