2014-10-20 125 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

如果你想有一個單親與多孩子應該更新,以便在父母更改時匹配父母,然後將父母的屬性改爲類屬性,並且「複製」到孩子將會自動完成。

如果你想有多個家長,至少有一些家長有孩子,有三個選項:

  • 使用授權(有孩子看在父母任何東西,它不知道約
  • 使用複製(你現在在做什麼)
  • 使用元類來創建一個新的父類爲每個不同的父母,那麼每個父有它的屬性類屬性。
相關問題