如何制作Python类的深拷贝?

2024-06-25 23:11:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我想复制一个类,同时更新它的所有方法以引用一组新的__globals__

我在想下面的事情,但是与types.FunctionType不同,types.UnboundMethodType的构造函数不接受{},有什么建议可以解决这个问题吗?在

def copy_class(old_class, new_module):
  """Copies a class, updating __globals__ of all methods to point to new_module"""

  new_dict = {}
  for name, entry in old_class.__dict__.items():
    if isinstance(entry, types.UnboundMethodType):
      entry = types.UnboundMethodType(name, None, old_class.__class__, globals=new_module.__dict__)
    new_dict[name] = entry
  return type(old_class.name, old_class.__bases__, new_dict)

Tags: to方法namenew事情old建议dict
2条回答

我不知道您的情况,但我通常不喜欢将types用于除类型检查之外的任何事情(我不经常这样做;-)。我宁愿inspect。。。在

我必须在这段代码的开头说,我希望您有一个很好的理由来做这件事;—)对我来说,似乎仅仅是子类化和重写类属性就可以更优雅地完成这项工作。。。但是,如果你真的想复制一个类,为什么不在新的命名空间中再次执行它的源代码呢?在

我将以下简单模块组合在一起:

# test.py
# Just some test data
FOO = 1

class Bar(object):
  def subclass_method(self):
    print('Hello World!')

class Foo(Bar):
  def method(self):
    return FOO

然后做些重活:

^{pr2}$

这可能有一些可取的性质和不可取的。。。首先,它只适用于可检查的类。这几乎是用户定义的任何东西,所以可能不是限制性的。。。它也可能比其他不需要重新解析源字符串的解决方案慢一点,但同样,它似乎不应该经常执行,所以这可能没问题。在

现在的“优势”。。。在

  1. 如果一个函数请求了一个全局,但没有提供,那么它将使用旧命名空间中的全局。如果这种行为不可取(即您宁愿使用NameError),您可以很容易地修改函数来删除它。在
  2. “副本”不是从原始文件继承的。在大多数情况下,这可能并不重要,但有一个东西的副本从原来的继承有点奇怪。。。在

有些人可能看到这里的exec,马上就会想:“哦,不!exec!?!?!世界就要结束了!!!”。弗兰基,这是个不错的默认回答。但是,我认为,如果您要复制一个计划在稍后的代码中使用的函数,那么它并不比使用exec更安全(毕竟,该函数的代码已经执行)。在

__dict__值是函数,而不是未绑定的方法。未绑定方法对象仅在属性访问时创建。如果您在__dict__中看到了未绑定的方法对象,那么在这个函数到达之前,类对象发生了一些奇怪的事情。在

相关问题 更多 >