当我从Python中继承实例而不是类时会发生什么? [英] What happens when I inherit from an instance instead of a class in Python?
问题描述
我很好奇当我将一个实例继承到一个类时会发生什么。
I'm just curious what will happen when I inherit an instance into a class.
所以我试过:
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()
我得到(至少)以下错误:
I get (at least) the following error:
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
我只是想知道:继承一个有意义/有用的实例或者只是简单的废话?
(问题有点学术性,特别是关于继承实例的细节。它不是关于对象委托或一般设计实践等替代方案。 )
(The question is a bit academic and specifically about the details of inheriting an instance. It's not about alternatives like object delegation or general design practices.)
推荐答案
类就像实例一样;他们有一个类型。对于类型是类的实例,但对于类,类型称为元类。从类继承通常会调用基类的元类型来生成一个新的类对象(使用 type(base)
;适用于多个碱基限制)。标准元类型是类型
对象,但您可以创建自己的元类。
Classes are just like instances; they have a type. For instances that type is the class, but for classes, the type is called a metaclass. Inheriting from a class normally would call the metatype of the base class to produce a new class object (using type(base)
; for multiple bases restrictions apply). The standard metatype is the type
object, but you can create your own metaclasses.
通过继承实例,Python尝试通过调用类型创建一个新类(obj)(classname,bases,body_namespace)
。由于 type(obj)
是 X
和 X .__ init __()
不支持这些参数,调用失败。但是,没有什么可以阻止你使这部分工作!
By inheriting from an instance, Python tries to create a new class by calling type(obj)(classname, bases, body_namespace)
. Since type(obj)
is X
and X.__init__()
doesn't support those arguments, the call fails. However, there is nothing stopping you from making that part work!
>>> 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对象位于0x ...>
而不是预期的< class'__main __。Child'>
,并且没有 __ call __
为类生成实例的方法。因此,使用实例作为另一个可以工作的基类,您只需要额外的工作来定义所有预期的功能。
Of course, type
provides a lot more functionality that a class won't offer out of the box; there are a series of descriptors to provide attributes on a class that other parts of Python expect to exist. Your class would have to cover all of those instead; in the above sample output, you'll note that repr(Child)
produces <__main__.X object at 0x...>
rather than the expected <class '__main__.Child'>
, and there is no __call__
method to produce instances for the class. So using an instance as a base class for another can work, you just have to put in the extra work to define all that expected functionality.
最后,使用实例作为基类是可能的,但没有实际使用,而不是当任何用例已被元类覆盖时。
In the end, using an instance as a base class may be possible, but has no practical uses, not when any of the use-cases are already covered by metaclasses instead.
这篇关于当我从Python中继承实例而不是类时会发生什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!