updated 2010-06-15T09:45:00Z
:
- 添加了“作为实例的类”方法的示例,以及对“作为类的实例”方法的解释;合并并引用了 Alex Martelli 的回答;
我想知道如何在 Python 中实现原型继承。这个问题似乎有两种不同的方法:作为实例的类和作为类的实例。
第二种方法似乎更灵活,因为它可以应用于各种类型的现有对象,而第一种方法对于典型用例可能更方便。
类作为实例
这里的想法是使用元类使实例化实际上是类,而不是对象。这种方法看起来像这样:
class ClassAsInstance(type):
""" ClassAsInstance(type)\n
>>> c = ClassAsInstance()
>>> c.prop = 6
It's sort of annoying to have to make everything a class method.
>>> c.jef = classmethod(lambda self: self.prop)
>>> c.jef()
6
>>> cc = c()
>>> cc.jef()
6
But it works.
>>> c.prop = 10
>>> cc.jef()
10
>>> c.jef = classmethod(lambda self: self.prop * 2)
>>> cc.jef()
20
"""
def __new__(self):
return type(self.__name__ + " descendant", (self, ), {})
我没有用这种方法真正测试过任何复杂的东西,所以它可能有局限性。
作为类的实例
使用这种方法,想法是使用type
构造函数从对象创建类。这在Alex Martelli 的回答中得到了例证,尽管他用于此方法的示例实现了复制原型,而不是允许后代继承对其原型的后续更改。
我的方法是做这样的事情:
def createDescendant(obj):
return type(obj.__class__.__name__ + " descendant", (obj.__class__, ), obj.__dict__)()
这将以一种 javascript-y 的方式工作:对给定对象的更改不会影响其后代,但对父对象__class__
(如 javascript prototype
)的更改会。我认为这是因为type
构造函数复制 obj.__dict__
而不是在某种 mro-ish 方案中引用它。
我试图实现一个允许真正的原型继承的改进版本,其中对象将继承对父对象的更新。这个想法是将原型对象的__dict__
属性分配给新创建的类的相同属性,即成为后代对象的类的属性。
但是,这并没有成功,因为我发现__dict__
atype
不能分配给;此限制也适用于从type
. 我仍然很好奇是否有可能通过创建一个“实现类型协议”的对象来解决这个问题,就像对可迭代对象、序列等所做的那样,但实际上并不继承自type
. 这可能会产生其他问题,例如亚历克斯在回答的第一部分中提到的授权方法所固有的问题。
代表团
Alex 还提出了第三种方法,即委托,其中对象的状态通过__getattr__
魔术方法传播到后代对象。同样,请参阅 Alex 的答案作为示例,以及有关此方法限制的详细信息。
特此要求进一步了解这些方法的实用性以及替代建议。