![](/img/trans.png)
[英]Python - Calling a Function Inside a For Loop - Changing Input Argument Without Overwriting It
[英]Python passing object as argument without overwriting
考虑以下代码:
class MyClass:
def __init__(self, x):
self.x = x
def myfunct(arg):
arg.x += 1
return arg
a = MyClass(0)
print(a.x)
b = myfunct(a)
print(a.x)
print(b.x)
返回:
0
1
1
我希望这段代码的行为与此代码相同:
def myfunct(arg):
arg += 1
return arg
c = 0
print(c)
d = myfunct(c)
print(c)
print(d)
但是,后者返回:
0
0
1
我了解这是由于Python通过赋值传递参数的方式(如本博文或本博文中所述) 。
但是,我找不到解决第一个代码中显示的行为的方法,这在我正在处理的项目中是不需要的。 如何将一个对象作为参数传递给函数,返回一个疯狂的对象,并保持原始对象不变?
您正在显式修改对象。 Python默认情况下支持此行为,但是如果要防止修改对象,则可能需要更新__setattr__
来管理属性修改。
如果要防止原始对象被修改,并且想要修改发送给该函数的对象,则可以向对象添加__copy__
方法以使其可以以自己喜欢的方式进行复制,然后使用将该对象的副本传递给该函数copy.copy()
。
class MyClass:
def __init__(self, x):
self.x = x
# default copy
def __copy__(self):
cls = self.__class__
result = cls.__new__(cls)
result.__dict__.update(self.__dict__)
return result
演示:
In [21]: a = MyClass(0)
...: print(a.x)
...:
0
# import copy
In [22]: b = myfunct(copy.copy(a))
In [24]: a.x
Out[24]: 0
In [25]: b.x
Out[25]: 1
简单的解决方案是仅创建或传递副本。 为此,您必须要有可能。 您可以在类上创建.copy()
方法,也可以使用copy
模块。
复制方法如下所示:
class MyClass:
def __init__(self, x):
self.x = x
def copy(self):
return self.__class__(self.x)
复制模块的工作方式如下:
import copy
b = copy.copy(a)
您可以使用任何一种方式来创建仅返回参数新副本的函数:
def myfunct(arg):
arg = arg.copy() # Or copy.copy(arg)
arg.x += 1
return arg
编辑:正如许多其他答案所说,如果您在可变对象中有可变对象(例如您的类的对象,其args
属性中具有该类的另一个对象),则上面显示的方法无效。 在这种情况下,请使用copy.deepcopy
函数:
def myfunct(arg):
arg = copy.deepcopy(arg)
arg.x += 1
return arg
from copy import deepcopy
def myfunct(arg):
new_arg = deepcopy(arg)
new_arg.x += 1
return new_arg
我建议深度复制而不是复制,因为您要确保切下所有对原始对象的引用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.