显而易见的解决方案是使用组合/委托而不是继承:
class Parent(object):
def __init__(self, name, number):
self.name = name
self.number = number
class Child(object):
def __init__(self, parent, other):
self.parent = parent
self.other = other
def __getattr__(self, name):
try:
return getattr(self.parent, name)
except AttributeError, e:
raise AttributeError("Child' object has no attribute '%s'" % name)
p = Parent("Foo", 42)
c = Child(p, "parrot")
print c.name, c.number, c.other
p.name = "Bar"
print c.name, c.number, c.other
当然,这是建立在您实际上不想要“副本”,而是“引用”的前提下。如果您真的想要一份副本,也是可能的,但对于可变类型会变得棘手:
import copy
class Parent(object):
def __init__(self, name, number):
self.name = name
self.number = number
class Child(object):
def __init__(self, parent, other):
for k, v in parent.__dict__.items():
self.__dict__[k] = copy.deepcopy(v)
self.other = other
如果上述解决方案都不适合您的需求,请解释您的实际用例 - 您可能存在 XY 问题。
[编辑] 的确有点像 XY 问题。真正的问题是:“如何将
peewee.Model
的字段复制到另一个
peewee.Model
中。
peewee
使用描述符(
peewee.FieldDescriptor
)来控制对模型字段的访问,并将字段名称和定义存储在模型的
_meta.fields
字典中,因此最简单的解决方案是迭代源模型的
_meta.fields
键,并使用
getattr
/
setattr
:
class RevisionMixin(object):
@classmethod
def copy(cls, source, **kw):
instance = cls(**kw)
for name in source._meta.fields:
value = getattr(source, name)
setattr(instance, name, value)
return instance
class Person(peewee.Model):
class PersonRevision(Person, RevisionMixin):
p = Person(name="foo", number=42)
r = PersonRevision.copy(p, whatelse="parrot")
NB:未经测试的代码,从未使用过 peewee
,可能有更好的选择...
peewee
源代码,我添加了一个“可能有效”的代码示例。同时,你应该真正了解一下“XY问题”……并不是说你的“解决方案”(最初的问题)完全错了,只是太泛泛而谈了。从一开始就陈述你的实际用例会让事情更加清晰,并避免了很多无畏的噪音。祝好运。 - bruno desthuilliers