如何深度复制具有包装函数的对象?
How can I deep copy an object which has a wrapped function?
所以我遇到了这个问题,我不明白一个变量以不同的方式显示,具体取决于我在容器中使用的函数,将它作为一个属性。我设法将其归结为以下代码:
import copy
from functools import wraps
def do_wrapping(func):
@wraps(func)
def wrapper(*args):
return func(*args)
return wrapper
class Container:
def __init__(self, var):
self.var = var
self.show = self._show_method
@property
def show(self):
return self._show
@show.setter
def show(self, shower):
self._show = do_wrapping(shower)
def _show_method(self):
print(self.var)
first_container = Container(1)
second_container = copy.deepcopy(first_container)
second_container.var = 0
second_container.show()
second_container._show_method()
我希望这两种方法都能打印出 0
,但第一种方法打印出 1
。
使用这一行 second_container.show = second_container._show_method
解决了这个问题,但我想避免它,因为它看起来很老套。
在我的真实情况下,包装有点复杂,所以我无法摆脱它。如果您移除包装,它会按预期工作。我假设包装后,函数有点像 "set in stone" 但我不知道如何解释它。
所以我的问题有两个:
- 为什么这段代码没有按预期工作(2 个输出是 0
)?
- 我该如何解决?
因为您正在使用 deepcopy
创建 second_container
,它的 __init__
方法永远不会被调用,所以它的 _show
属性是从 first_container
复制的秒。由于 first_container._show
是一个包装 first_container._show_method
的函数,这就是您调用 second_container.show()
时得到的结果
对于您的简单示例,您可以只调用 second_container.__init__(0)
而不是 second_container.var = 0
。这有点不寻常,但它可能适用于您的实际代码。
如果您不能调用复制对象的 __init__
方法,我认为我的首选方法是在调用 show
getter 时进行函数包装,而不是比 __init__
时间:
class ContainerParent(object):
@property
def show(self):
return do_wrapping(self._show)
@show.setter
def show(self, shower):
self._show = shower
如果那不可行,好吧,还有很多其他可能性 - 例如,您可以将 var
设为 属性 并将 self.show = self._show_method
行移动到其 setter - 但如果不了解您的实际代码,很难说什么是最好的。
所以我遇到了这个问题,我不明白一个变量以不同的方式显示,具体取决于我在容器中使用的函数,将它作为一个属性。我设法将其归结为以下代码:
import copy
from functools import wraps
def do_wrapping(func):
@wraps(func)
def wrapper(*args):
return func(*args)
return wrapper
class Container:
def __init__(self, var):
self.var = var
self.show = self._show_method
@property
def show(self):
return self._show
@show.setter
def show(self, shower):
self._show = do_wrapping(shower)
def _show_method(self):
print(self.var)
first_container = Container(1)
second_container = copy.deepcopy(first_container)
second_container.var = 0
second_container.show()
second_container._show_method()
我希望这两种方法都能打印出 0
,但第一种方法打印出 1
。
使用这一行 second_container.show = second_container._show_method
解决了这个问题,但我想避免它,因为它看起来很老套。
在我的真实情况下,包装有点复杂,所以我无法摆脱它。如果您移除包装,它会按预期工作。我假设包装后,函数有点像 "set in stone" 但我不知道如何解释它。
所以我的问题有两个:
- 为什么这段代码没有按预期工作(2 个输出是 0
)?
- 我该如何解决?
因为您正在使用 deepcopy
创建 second_container
,它的 __init__
方法永远不会被调用,所以它的 _show
属性是从 first_container
复制的秒。由于 first_container._show
是一个包装 first_container._show_method
的函数,这就是您调用 second_container.show()
对于您的简单示例,您可以只调用 second_container.__init__(0)
而不是 second_container.var = 0
。这有点不寻常,但它可能适用于您的实际代码。
如果您不能调用复制对象的 __init__
方法,我认为我的首选方法是在调用 show
getter 时进行函数包装,而不是比 __init__
时间:
class ContainerParent(object):
@property
def show(self):
return do_wrapping(self._show)
@show.setter
def show(self, shower):
self._show = shower
如果那不可行,好吧,还有很多其他可能性 - 例如,您可以将 var
设为 属性 并将 self.show = self._show_method
行移动到其 setter - 但如果不了解您的实际代码,很难说什么是最好的。