2014-10-20 124 views
3

我有两个班,其中一个从其​​他继承:如何将一个Python对象的所有属性复制到另一个?

class DaParent(object): 
    name = '' 
    number = 0 

class DaChild(DaParent): 
    additional = '' 

我现在创造一个家长和更改属性:

parent = DaParent() 
parent.name = 'papa' 
parent.number = 123 

而且从这个角度,我想创建一个子项,我想从父项中复制所有属性。当然,我可以做到这一点,像这样:

child = DaChild() 
child.name = parent.name 
child.number = parent.number 

的事情是,在开发,这个类将增长到有相当大量的属性,我不经常要换的手动复制属性进入孩子。

有没有办法自动接管父对象的属性到一个新的子对象?欢迎所有提示!

[编辑] 只是为了解释为什么我想这样做。我使用Peewee ORM与我的数据库进行交互。我现在想修改一个表格(意思是如果一个记录被更新,我想保留所有以前的版本)。我打算这样做的方式是,例如创建一个Person类和一个PersonRevision类,该类继承Person类。然后,我重写peewee save() method以不仅保存Person对象,而且还将所有属性复制到PersonRevision对象中并保存。由于我绝对不会直接与PersonRevision班互动,所以我不需要阴影或任何花哨的东西。我只想复制这些属性并调用它的对象save()方法。

+3

你采取行动真的希望这些是* class *,而不是* instance *属性? – jonrsharpe 2014-10-20 14:05:03

+0

@jonrsharpe - 据我所知他们需要是实例属性,所以属性的对象,而不是类本身。 – kramer65 2014-10-20 14:10:19

+0

这是**不是**你现在拥有的 - 在'class'内定义的属性,但在实例方法'def'之外定义的属性是* class attributes *。 – jonrsharpe 2014-10-20 14:21:26

回答

7

显而易见的解决方案是使用合成/委托,而不是传承的:

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): 
     # only copy instance attributes from parents 
     # and make a deepcopy to avoid unwanted side-effects 
     for k, v in parent.__dict__.items(): 
      self.__dict__[k] = copy.deepcopy(v) 
     self.other = other 

如果这些解决方案的满足您的需求,请说明您真正使用情况 - 你可能有一个XY问题。

边界上的XY问题的确如此。真正的问题是:“如何将peewee.Model的字段复制到另一个peewee.Modelpeewee使用描述符(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): 
    # fields defintions here 


class PersonRevision(Person, RevisionMixin): 
    # additional fields definitions here 


p = Person(name="foo", number=42) 
r = PersonRevision.copy(p, whatelse="parrot") 

注意:未经测试的代码,从来没有使用过peewee,有可能是更好的东西做...

0

如果你想有一个单亲与多孩子应该更新,以便在父母更改时匹配父母,然后将父母的属性改为类属性,并且“复制”到孩子将会自动完成。

如果你想有多个家长,至少有一些家长有孩子,有三个选项:

  • 使用授权(有孩子看在父母任何东西,它不知道约
  • 使用复制(你现在在做什么)
  • 使用元类来创建一个新的父类为每个不同的父母,那么每个父有它的属性类属性。
相关问题