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—虚子类—对象继承
为什么要用抽象类来扩展抽象类
假设你的项目更复杂。你可以有抽象类,比如},然后是具体的类,比如}(现在让我们忽略一些狗游泳和一些鱼走路):
Animal
,LandAnimal
和{Dog
,Wolf
和{在这种实现中,“中间”抽象类非常有用,因为它们同意避免重复代码,如
LandAnimal
示例中所示。在当然,这段代码也可以使用decorator而不是抽象方法
move
上的子类来实现,但是通常情况下,当抽象子类包装的代码很重要或者至少在语义上有优势时,人们更喜欢抽象子类。在它们是如何在python中实现的
在python中,您可以创建一个抽象类,方法是在不重写时向它添加一个引发异常的方法,如:
或者,在python“>;2.6”中,您可以使用^{} ,这个包提供了创建抽象类所需的基本所有信息,例如decorator和
^{pr2}$ABC
(抽象基类):我读了Interfaces in Python: Protocols and ABCs,它让我有了更好的理解。我们有Python中的duck类型:
但是,}都可以
Bird
和{fly()
。但它们不是一回事。因此,我们需要定义一个接口来区分它们。(Python没有interface
关键字,因此我们实际上使用的是抽象类)我来举个例子:
我们的程序中有}。它们都实现了
Duck
和{fly()
方法。现在我们想从机库里选一架飞机,让一些人上飞机,然后飞到另一个城市。显然,我们不能把人放在Duck
上,所以我们定义了一个名为Plane
的接口(实际上是一个抽象类)。我们让MyPlane
子类Plane
。在一切正常。当我们想选择一个平面时,我们检查它是否是
Plane
的子类。然而,波音公司开发了一个包,它有一个Boeing747Plane
。我们买了那架飞机(from boeing-airplanes import Boeing747Plane
),但它不是公认的飞机。它确实有一个fly()
方法,但它不是从我们的Plane
类继承的,所以我们的Python解释器不会将它识别为平面。在好消息是Python是一种灵活的语言。感谢}的子类。我们可以使用第三方
register
的register
方法,在我们完成Plane.register(Boeing747Plane)
之后,Boeing747Plane
现在是{Boeing747Plane
,就像我们自己构建的Plane
。万岁!在所以你看,当我们想把一个来自第三方包的类变成我们自己的抽象类的子类时,就会用到虚拟类。我们希望它实现我们的接口,但是我们不能改变它的代码,所以我们明确地告诉解释器“它实现了我们的接口,请把它当作我们自己类的子类”。我想通常我们不想用它,但当你需要的时候,要谨慎使用。 正如lucacappelletti所说,这是Python遵循其“我们在这里是成年人”的理念所允许的众多灵活性之一。在
相关问题 更多 >
编程相关推荐