python:如何将所有的attribute从基类复制到派生的attribute

Python: How to copy all attibutes from base class to derived one

我希望实现以下目标:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/python
class SuperHero(object):
    def setName(self, name):
        self.name = name
    def getName(self):
        return self.name

class SuperMan(SuperHero):
    pass

if __name__ =="__main__":
    sh = SuperHero()
    sh.setName("Clark Kent")
    sm = SuperMan(sh)  # This does *not* work in real python
    print sm.getName() # prints"Clark Kent"

我需要一个接一个地复制属性吗,还是有更好的方法来做?


添加在__dict__属性中复制的发起程序函数:

1
2
3
4
class SuperMan(SuperHero):
    def __init__(self, source=None):
        if source is not None:
            self.__dict__.update(source.__dict__)

一个实例的__dict__拥有所有的实例属性,以上只是将所有这些属性复制到新的SuperMan实例。

演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> class SuperHero(object):
...     def setName(self, name):
...         self.name = name
...     def getName(self):
...         return self.name
...
>>> class SuperMan(SuperHero):
...     def __init__(self, source=None):
...         if source is not None:
...             self.__dict__.update(source.__dict__)
...
>>> sh = SuperHero()
>>> sh.setName("Clark Kent")
>>> sm = SuperMan(sh)
>>> print sm.getName()
Clark Kent

或者,对于更糟糕的黑客,您可以换掉class属性:

1
2
3
sh = SuperHero()
sh.setName("Clark Kent")
sh.__class__ = SuperMan

但这会导致更有趣的错误,因为您从未调用过SuperMan初始值设定项,因此预期状态可能不正确。


我更喜欢明确的解决方案——一个接一个地复制。Martijn Pieters的解决方案很好,但随着时间的推移,您的__dict__可能会增长,您可能不想复制它的所有内容(或更糟的是,忘记这一事实,体验一些讨厌的副作用)。除了Python的禅说:Explicit is better than implicit.

旁注-你知道属性,对吗?所以如果你使用的话,你的代码可能更像Python:

1
2
3
4
5
6
7
8
9
10
class SuperHero(object):
    @property
    def name(self):
        return self._name
    @name.setter
    def name(self, name):
        self._name = name

sh = SuperHero()
sh.name ="Clark Kent"