虚拟子类的用途是什么?

2024-09-30 05:30:08 发布

您现在位置:Python中文网/ 问答频道 /正文

class AnimalMeta(type):
    def __instancecheck__(cls, instance):
        return cls.__subclasscheck__(type(instance))

    def __subclasscheck__(cls, sub):
        return (hasattr(sub, 'eat') and callable(sub.eat) and
                hasattr(sub, 'sleep') and callable(sub.sleep))


class Animal(object):
    __metaclass__ = AnimalMeta
    pass


class Dog(object):
    def eat(self):
        print "eat"
    def sleep(self):
        print "sleep"


dog = Dog()
dog.eat()

print isinstance(dog, Animal)
print issubclass(dog, Animal)

输出:

^{pr2}$

我试图理解python虚拟子类,示例如上图所示。实例一个虚拟子类根本不需要实现抽象方法。在

虚拟子类的真实用例是什么?在我看来,虚拟子类的工作方式类似于duck类型和object inherit的中间。在

Duck type—虚子类—对象继承


Tags: andinstancereturnobjectdeftypesleep子类
2条回答

为什么要用抽象类来扩展抽象类

假设你的项目更复杂。你可以有抽象类,比如AnimalLandAnimal和{},然后是具体的类,比如DogWolf和{}(现在让我们忽略一些狗游泳和一些鱼走路):

Structure implementation

在这种实现中,“中间”抽象类非常有用,因为它们同意避免重复代码,如LandAnimal示例中所示。在

当然,这段代码也可以使用decorator而不是抽象方法move上的子类来实现,但是通常情况下,当抽象子类包装的代码很重要或者至少在语义上有优势时,人们更喜欢抽象子类。在

它们是如何在python中实现的

在python中,您可以创建一个抽象类,方法是在不重写时向它添加一个引发异常的方法,如:

class A:
    def my_abstract_method(self):
        raise NotImplementedError("You should override 'my_abstract_method'")

或者,在python“>;2.6”中,您可以使用^{},这个包提供了创建抽象类所需的基本所有信息,例如decorator和ABC(抽象基类):

^{pr2}$

我读了Interfaces in Python: Protocols and ABCs,它让我有了更好的理解。我们有Python中的duck类型:

If it talks and walks like a duck, then it is a duck.

但是,Bird和{}都可以fly()。但它们不是一回事。因此,我们需要定义一个接口来区分它们。(Python没有interface关键字,因此我们实际上使用的是抽象类)

我来举个例子:

我们的程序中有Duck和{}。它们都实现了fly()方法。现在我们想从机库里选一架飞机,让一些人上飞机,然后飞到另一个城市。显然,我们不能把人放在Duck上,所以我们定义了一个名为Plane的接口(实际上是一个抽象类)。我们让MyPlane子类Plane。在

一切正常。当我们想选择一个平面时,我们检查它是否是Plane的子类。然而,波音公司开发了一个包,它有一个Boeing747Plane。我们买了那架飞机(from boeing-airplanes import Boeing747Plane),但它不是公认的飞机。它确实有一个fly()方法,但它不是从我们的Plane类继承的,所以我们的Python解释器不会将它识别为平面。在

好消息是Python是一种灵活的语言。感谢registerregister方法,在我们完成Plane.register(Boeing747Plane)之后,Boeing747Plane现在是{}的子类。我们可以使用第三方Boeing747Plane,就像我们自己构建的Plane。万岁!在

所以你看,当我们想把一个来自第三方包的类变成我们自己的抽象类的子类时,就会用到虚拟类。我们希望它实现我们的接口,但是我们不能改变它的代码,所以我们明确地告诉解释器“它实现了我们的接口,请把它当作我们自己类的子类”。我想通常我们不想用它,但当你需要的时候,要谨慎使用。 正如lucacappelletti所说,这是Python遵循其“我们在这里是成年人”的理念所允许的众多灵活性之一。在

相关问题 更多 >

    热门问题