当我从Python中继承实例而不是类时会发生什么? [英] What happens when I inherit from an instance instead of a class in Python?

查看:133
本文介绍了当我从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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆