给出以下代码
class Test():
def __init__(self, foo):
self._foo = foo
a = Test("bar") # id(a) returns e.g. 2243221358240
b = Test("rab") # id(b) returns e.g. 2243221358184
我想将b
引用的对象复制到a
的位置,以便id(a)
仍然返回原始地址,但a._foo
会返回rab
}。
什么是" pythonic"这样做的方法?
这在Python中是否可行?
答案 0 :(得分:3)
Python不是C,谈论将一个实例的内存复制到另一个实例之上是没有意义的。您可以通过将所有属性从一个实例复制到另一个实例来实现类似的结果。
在大多数Python对象中,属性存储在名为__dict__
的实例属性中,除非该类具有sa __slots__
属性,该属性定义了允许属性的名称。 / p>
许多内置的Python对象都是用C实现的,因此不具备这些属性中的任何一个。这些通常不能以任何合理的自动化方式通过属性进行复制。
通过这些警告,您可以执行以下操作:
def copy_attributes(obj1, obj2):
if not isinstance(obj1, type(obj2)) and not isinstance(obj2, type(obj1)):
raise TypeError("source and target object types must be related somehow")
# fast path if both have __dict__
if hasattr(obj1, "__dict__") and hasattr(obj2, "__dict__"):
obj2.__dict__.update(obj1.__dict__)
return
# copy one attribute at a time
names = getattr(type(obj1), "__slots__", ()) and getattr(obj1, "__dict__", ())
slots = set(getattr(type(obj2), "__slots__", ()))
if slots and not all(name in slots for name in names):
raise AttributeError("target lacks a slot for an attribute from source")
for name in names:
setattr(obj2, getattr(obj1, name))
我编写此函数的方式,两个实例必须相关(一个是另一个类型的子类)。这增加了实际工作的可能性,虽然取决于类的设置方式,它可能会也可能不会导致obj2
的有用配置,除非它们是完全相同的类型。也就是说,obj2
具有obj1
但if type(obj1) is not type(obj2)
不具有的属性将保留其原始值,这可能会产生不一致的对象。您可能更喜欢更严格的类型检查:例如obj2
。
如果__slots__
的{{1}}类型obj1
和obj2
具有__slots__
中不允许的属性,那么您将尝试错误设置这些属性。在这种情况下,我检查以确保要复制的所有属性都存在于copy.copy
中。否则你最终可能没有复制所有属性。
如果您知道要使用的类型,可以出于性能原因删除部分或全部安全检查。
请注意,此类上定义的属性(包括方法)不会被此函数复制;它只复制实例属性。副本很浅,因此共享可变对象。如果这很重要,您可以添加copy.deepcopy
或{{1}}来电。