我只是好奇当我将一个实例继承到一个类时会发生什么。
所以我试过了:
class X:
def __init__(self, x):
self.x = x
def print(self):
print(self.x)
def inherit(obj):
class Child(obj): # Line 20
pass # or maybe added functionality
return Child
param = 5
x = X(param)
y = inherit(x) # Line 27
y.print()
我得到(至少)以下错误:
Traceback (most recent call last):
File "/test.py", line 27, in <module>
y = inherit(x)
File "/test.py", line 20, in inherit
class Child(obj):
TypeError: __init__() takes 2 positional arguments but 4 were given
我只是想知道:是继承一个有意义/有用的实例还是简单的废话?
(问题有点学术性,特别是关于继承实例的细节。这不是关于对象委托或一般设计实践等替代方案。)
答案 0 :(得分:9)
类就像实例一样;他们有一个类型。对于类型是类的实例,但对于类,该类型称为元类。从类继承通常会调用基类的元类型来生成一个新的类对象(使用type(base)
;适用于多个碱基限制)。标准元类型是type
对象,但您可以create your own metaclasses。
通过从实例继承,Python尝试通过调用type(obj)(classname, bases, body_namespace)
来创建一个新类。由于type(obj)
为X
且X.__init__()
不支持这些参数,因此调用失败。但是,没有什么可以阻止你使这部分工作!
>>> class X:
... def __init__(self, classname, parents, namespace):
... print('Creating {}{}'.format(classname, parents))
...
>>> class Child(X('X', (), {})): pass
...
Creating X()
Creating Child(<__main__.X object at 0x10372b4a8>,)
>>> Child
<__main__.X object at 0x10372b470>
>>> Child()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'X' object is not callable
当然,type
提供了更多功能,一个类不会提供开箱即用的功能;有一系列描述符可以提供Python的其他部分期望存在的类的属性。你的班级必须覆盖所有这些;在上面的示例输出中,您会注意到repr(Child)
生成<__main__.X object at 0x...>
而不是预期的<class '__main__.Child'>
,并且没有__call__
方法来为类生成实例。因此,使用实例作为另一个可以工作的基类,您只需要额外的工作来定义所有预期的功能。
最后,使用实例作为基类是可能的,但是没有实际使用,而不是当任何用例已经由元类覆盖时。
答案 1 :(得分:-2)
Python引人注目的是一种基于原型的面向对象设计模型。这意味着所有东西,甚至是类,都是Pythonic世界中的对象。 https://en.wikipedia.org/wiki/Prototype-based_programming
Python中的继承关系是通过引用其类的实例中的引用来执行的。这是类。您可以在运行时将此引用更改为任何其他类。如果您这样做是为了在运行时更改实例的行为,那么您正在实现动态继承。例如,考虑一个元素列表的实例, ListOfOne 类,它有适当的方法来处理一个元素。如果添加了其他元素,则类引用可能会更改为 RegularList 。如果列表已清空,则其类可以更改为 EmptyList 。
不幸的是(或者不是)Python隐藏了所有这些。例如,您在类标签下创建原型,并禁止在此视图下完全合法的一些操作。因此,可以从实例继承,但Python否认了这种可能性。