在Python中模仿传值的行为
我想模仿python中的传值行为。 换句话说,我想确保我写的函数不会修改用户提供的数据。
一种可能的方法是使用深层复制:
from copy import deepcopy def f(data): data = deepcopy(data) #do stuff
是否有更高效或更pythonic的方式来实现这一目标,尽可能less的假设尽可能传递的对象(如.clone()方法)
编辑
我知道在技术上,python中的所有东西都是按值传递的。 我对模拟行为感兴趣,也就是确保我不会混淆传递给函数的数据。 我想最通用的方法是用自己的克隆机制或深度拷贝克隆有问题的对象。
没有pythonic这样做的方式。
Python提供了很less的工具来执行诸如私有或只读数据之类的东西。 pythonic哲学是“我们都同意成年人”:在这种情况下,这意味着“函数不应该改变数据”是规范的一部分,但没有在代码中强制执行。
如果您想制作一份数据副本,您可以得到最接近的解决scheme。 但是copy.deepcopy
除了效率低下外,还有一些注意事项, 比如 :
因为深拷贝复制了可能拷贝太多的所有内容,例如,即使在拷贝之间也应该共享的pipe理数据结构。
[…]
该模块不复制模块,方法,堆栈跟踪,堆栈框架,文件,套接字,窗口,数组或任何类似types的types。
所以我只推荐它,如果你知道你正在处理内置的Pythontypes或你自己的对象(你可以通过定义__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)
你甚至可以让装饰器采取一些克隆的function,从而允许装饰器的用户决定克隆策略。 在这种情况下,装饰器可能被最好的实现为__call__
覆盖的类。
例如,只有几个内build的types可以用作引用,比如list
。
所以,对于我来说,在这个例子中,做一个按价值传递的pythonic方式是:
list1 = [0,1,2,3,4] list2 = list1[:]
list1[:]
创buildlist1[:]
的新实例,并且可以将其分配给一个新的variables。
也许你可以写一个可以接收一个参数的函数,然后检查它的types,并根据这个结果执行一个内build操作,该操作可以返回一个新的参数实例。
正如我刚才所说,只有less数内buildtypes,他们的行为就像参考资料,在这个例子中列出。
任何方式…希望它有帮助。
通常在将数据传递给外部API时,可以通过将数据作为不可变对象传递来确保数据的完整性,例如将数据包装到元组中。 这不能被修改,如果这是你试图阻止你的代码。
我找不出任何其他pythonic选项。 但是,我个人更喜欢更多的OO方式。
class TheData(object): def clone(self): """return the cloned""" def f(data): #do stuff def caller(): d = TheData() f(d.clone())
虽然我确信没有真正的pythonic的方式来做到这一点,但我希望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]
还有一个窍门
数字variables
a = 0
函数调用(a + 0)
stringvariables
a ='testing数据'
函数调用(a +'')
布尔variables
a =真
函数调用(a和True)