0

self我想用执行时传递的原始副本执行一个方法。

这是我正在谈论的代码:

def protect_self(func):
    from copy import copy
    from functools import wraps
    @wraps(func)
    def decorated(self, *args, **kwargs):
        self_copy = copy(self)
        return func(self_copy, *args, **kwargs)
    return decorated

据我了解,复制函数会创建一个相同类型的新对象__dict__并将旧对象复制到新对象(使用引用,因此对实际对象实例的更改__dict__仍会影响原始对象)。

这是否意味着我可以确定装饰方法不能修改__dict__原始实例?

只是为了确保:我不需要安全的沙盒行为。我的目的只是实例化一个我将用作工厂的对象。受 保护的方法应该可以修改传递的self,但之后应该重置。

4

2 回答 2

2

副本使得传递给装饰函数的“自我”是原始的浅拷贝。装饰函数不能直接修改原来的'self',虽然它当然可以通过其他方式修改(如果它有间接访问它的话)。如果对象的任何属性是可变的,它可以有效地改变原来的'self'通过修改属性。

此外,任何一段(任意)Python 代码都可以间接访问程序中的几乎所有对象。gc例如,装饰函数可以通过堆栈检查或通过模块访问原始“自我” 。你的用例似乎有点复杂;你确定你应该为此使用一个类实例吗?

于 2010-01-22T21:20:26.780 回答
1

正如 OP 在评论中澄清的那样,目的是线程安全的,那么有一个明显的问题——copy.copy它本身不是线程安全的,除了已经指出的问题之外,它copy.copy会产生拷贝等等(虽然self.__dict__它本身不会被修改)可变对象可以很好地被改变。使用copy.deepcopy处理这个问题(在性能方面可能付出高昂的代价)但在某种意义上甚至会恶化线程安全问题(因为深度复制可能比浅层复制花费更长的时间,竞争条件的风险实际上发生突飞猛进 - 并不是说​​我以任何方式,形状或形式都建议让比赛条件“很少”发生,请注意!-)。

如果您必须使原本不安全的方法成为线程安全的,那么您将不得不咬紧牙关并使用锁(或队列和辅助线程来序列化操作)——我想如果您进一步需要默默地忽略方法试图改变对象,你还必须做deepcopy所有事情(为什么要停下来self——例如,如果这些方法正在改变全局变量呢?!-)。对我来说似乎是一个非常不确定的提议。

于 2010-01-23T03:24:37.477 回答