考虑以下代码:
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通过赋值传递参数的方式,如this post或this post中所述。
但是,我无法找到解决第一个代码中显示的行为的方法,这在我正在处理的项目中是不需要的。如何将对象作为参数传递给函数,返回一个疯狂的对象,并保持原始对象不变?
答案 0 :(得分:1)
您明确修改了对象。 Python默认支持此行为,但如果您想阻止修改对象,可能需要更新__setattr__
以管理属性修改。
如果您想要阻止修改原始对象,并且您想要修改发送到该函数的对象,您可以{_ 3}}以您喜欢的方式进行复制,然后将对象的副本传递给该函数使用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
答案 1 :(得分:0)
简单的解决方案是,只需创建或传递副本。要做到这一点,你必须有可能。您可以在课程上创建.copy()
方法,也可以使用copy
模块。
复制方法可能如下所示:
class MyClass:
def __init__(self, x):
self.x = x
def copy(self):
return self.__class__(self.x)
copy module的工作原理如下:
import copy
b = copy.copy(a)
您可以使用任一方式创建一个只返回参数的新副本的函数:
def myfunct(arg):
arg = arg.copy() # Or copy.copy(arg)
arg.x += 1
return arg
编辑:正如许多其他答案所说,如果你在可变对象中有可变对象(例如你的类的一个对象,你的类的另一个对象在其{{1}中),上面显示的方法并不起作用属性)。在这种情况下,请改用args
函数:
copy.deepcopy
答案 2 :(得分:0)
from copy import deepcopy
def myfunct(arg):
new_arg = deepcopy(arg)
new_arg.x += 1
return new_arg
我建议对拷贝进行深度复制,因为你要确保切断对原始对象的所有引用。