代码之家  ›  专栏  ›  技术社区  ›  Gregor Müllegger

当方法修饰器替换self时,应该有什么副作用?

  •  0
  • Gregor Müllegger  · 技术社区  · 15 年前

    我想用原始文件的副本执行一个方法 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
    

    在我的理解中,copy函数创建了一个相同类型的新对象,并且 复制 __dict__ 新对象的旧对象(使用引用,所以 对中实际对象实例的更改 第二节 仍会影响原始对象)。

    这是否意味着我可以确定修饰方法不能修改 第二节 属于 原始实例?

    只是为了确保:我不需要安全的沙盒行为。我的目的只是 有一个单独的对象,我将作为一个工厂使用。这个 受保护的 方法应该可以修改传递的 自己 但它应该 之后重新植入。

    2 回复  |  直到 15 年前
        1
  •  1
  •   Alex Martelli    15 年前

    正如OP在一篇评论中澄清的那样,目的是为了安全起见,那么有一个明显的问题。-- copy.copy 它本身 不是 除了已经指出的问题外,THREADSAFE还指出 复印件 做一个 浅的 复制等(同时 self.__dict__ 它本身不会被修改)可变对象完全可以被修改。使用 copy.deepcopy 处理这个问题(在性能方面可能要付出巨大的代价),但在某种意义上甚至会恶化线程安全问题(因为深度复制可能比浅层复制要花费更长的时间,因此实际发生竞争条件的风险会急剧增加,而不是我以任何方式、形状或形式 推荐 有“很少”发生的比赛条件,注意!-)

    如果必须使原来不安全的方法成为线程安全的,则必须咬紧牙关并使用锁(或队列和辅助线程来序列化操作)——我猜,如果进一步需要静默地忽略方法更改对象的尝试,则还必须 deepcopy 一切(为什么停在 self --如果那些方法改变了呢 全局变量 比如说?!)对我来说,这似乎是一个非常含糊的建议。

        2
  •  2
  •   Thomas Wouters    15 年前

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

    另外,任何一段(任意)python代码都可以间接访问程序中的几乎任何对象。修饰函数可以通过堆栈检查或通过 gc 例如,模块。您的用例看起来有点复杂;您确定应该为此使用类实例吗?