跳转到主要内容

抽象类和接口定义

项目描述

抽象类和接口定义。

创建一个 abstract.Abstraction

Abstraction 是定义抽象类的元类。

让我们定义一个抽象类 AFoo 并给它一个抽象方法 do_foo

与任何Python类一样,Abstraction 可以有任意的名字,但通过在名称前缀加上 A 可能有助于区分抽象类和其他类。

>>> import abc
>>> import abstracts

>>> class AFoo(metaclass=abstracts.Abstraction):
...
...     @abc.abstractmethod
...     def do_foo(self):
...         raise NotImplementedError

抽象类 不能 被直接实例化。

>>> AFoo()
Traceback (most recent call last):
...
TypeError: Can't instantiate abstract class AFoo with abstract method... do_foo

abstract.Abstraction 创建一个实现者

为了使用 AFoo,我们需要为它创建一个实现者。

>>> @abstracts.implementer(AFoo)
... class Foo:
...     pass

实现者 必须 实现其抽象类定义的所有抽象方法。

>>> Foo()
Traceback (most recent call last):
...
TypeError: Can't instantiate abstract class Foo with abstract method... do_foo

>>> @abstracts.implementer(AFoo)
... class Foo2:
...
...     def do_foo(self):
...         return "DID FOO"

>>> Foo2()
<__main__.Foo2 object at ...>

实现者继承自其 Abstractions

实现者类是其 Abstraction 的子类。

>>> issubclass(Foo2, AFoo)
True

同样,实现者实例是其 Abstraction 的实例

>>> isinstance(Foo2(), AFoo)
True

Abstraction 类可以在类 bases 中看到,并且实现者可以调用 Abstraction 的方法。

>>> import inspect
>>> AFoo in inspect.getmro(Foo2)
True

创建一个实现多个抽象实现者

实现者可以实现多个抽象。

让我们创建第二个抽象。

>>> class ABar(metaclass=abstracts.Abstraction):
...
...     @abc.abstractmethod
...     def do_bar(self):
...         raise NotImplementedError

现在我们可以创建一个实现者,它同时实现AFooABar抽象

>>> @abstracts.implementer((AFoo, ABar))
... class FooBar:
...
...     def do_foo(self):
...         return "DID FOO"
...
...     def do_bar(self):
...         return "DID BAR"

>>> FooBar()
<__main__.FooBar object at ...>

定义抽象属性

属性可以在抽象类中定义,就像普通方法一样,任何实现者都必须实现它们。

>>> class AMover(metaclass=abstracts.Abstraction):
...
...     @property
...     @abc.abstractmethod
...     def speed(self):
...         return 5
...
...     @property
...     @abc.abstractmethod
...     def direction(self):
...         return "forwards"

abstractmethod中调用super()

就像Python的“抽象基类”一样,你可以在abstractmethod中调用super()来调用抽象实现。

>>> @abstracts.implementer(AMover)
... class Mover:
...
...     @property
...     def direction(self):
...         return "backwards"
...
...     @property
...     def speed(self):
...         return super().speed

这个自定义的AMover实现必须实现speeddirection,即使它的实现调用了抽象实现。

在这种情况下,它使用了默认/抽象的speed实现,同时提供了它自己的direction实现。

>>> mover = Mover()
>>> mover
<__main__.Mover object at ...>

>>> mover.speed
5
>>> mover.direction
'backwards'

定义abstracts.Interface

Interface抽象类似,但有一些区别。

Interface只能使用@interfacemethod装饰器定义方法。

它不能定义普通方法或带有@abstractmethod的方法,只能定义带有@interfacemethod的方法。

如果调用@interfacemethod,将始终引发一个NotImplementedError,因此不能用作抽象实现。

让我们添加一个我们可以使用的Interface类。

就像区分抽象与其他类型的类可能有所帮助一样,使用I前缀命名它们也可能有助于区分Interface

>>> class IGeared(metaclass=abstracts.Interface):
...
...     @property
...     @abstracts.interfacemethod
...     def number_of_gears(self):
...         # Raising an error is ~superfluous as the decorator will raise
...         # anyway if the method is invoked.
...         raise NotImplementedError

实现一个Interface

就像实现抽象一样,可以使用@implementer装饰器实现Interface

实现者可以实现抽象Interface的组合。

>>> @abstracts.implementer((AMover, IGeared))
... class Bicycle:
...
...     @property
...     def direction(self):
...         return super().direction
...
...     @property
...     def speed(self):
...         return super().speed
...
...     @property
...     def number_of_gears(self):
...         return 7

>>> Bicycle().number_of_gears
7

实现者从其Interface继承

实现者类是其Interface的子类。

>>> issubclass(Bicycle, AMover)
True
>>> issubclass(Bicycle, IGeared)
True

同样,实现者的一个实例是其Interface的一个实例。

>>> isinstance(Bicycle(), AMover)
True
>>> isinstance(Bicycle(), IGeared)
True

抽象不同,它继承自其Interface

>>> AMover in inspect.getmro(Bicycle)
True

>>> IGeared in inspect.getmro(Bicycle)
False

@interfacemethods永远不会被调用

要记住的关键一点是,你不能在@interfacemethod上调用super()或直接调用它。

如果它在Interface中定义为部分,你将收到一个AttributeError,因为实现没有直接从接口继承。

>>> @abstracts.implementer((AMover, IGeared))
... class BrokenBicycle:
...
...     @property
...     def direction(self):
...         return super().direction
...
...     @property
...     def speed(self):
...         return super().speed
...
...     @property
...     def number_of_gears(self):
...         return super().number_of_gears

>>> BrokenBicycle().number_of_gears
Traceback (most recent call last):
...
AttributeError: 'super' object has no attribute 'number_of_gears'

如果你在一个作为抽象一部分定义的@interfacemethod上调用super(),它将引发NotImplementedError

由于Interface只能包含此类方法,因此你永远不能调用其任何方法。直接这样做将引发一个NotImplementedError

>>> IGeared.number_of_gears.__get__(Bicycle())
Traceback (most recent call last):
...
NotImplementedError

抽象中组合@abstractmethod@interfacemethod

由于接口是“纯的”,因此它们不能使用@abstractmethod或包含任何实现。

另一方面,抽象可以同时结合这两者。

让我们创建一个纯接口,表示“车库”。

>>> class IShed(metaclass=abstracts.Interface):
...
...     @property
...     @abstracts.interfacemethod
...     def size(self):
...         raise NotImplementedError

我们可以使用这个接口来创建一个ABikeShed 抽象

>>> class ABikeShed(IShed, metaclass=abstracts.Abstraction):
...
...     @property
...     @abstracts.interfacemethod
...     def max_bike_size(self):
...         raise NotImplementedError
...
...     @abc.abstractmethod
...     def get_capacity(self):
...         return int(self.size / self.max_bike_size)

现在我们可以创建一个实现。

它需要定义sizemax_bike_size,因为这些是interfacemethods

然而,它可以利用get_capacity的抽象实现,即使它必须被定义。

>>> @abstracts.implementer(ABikeShed)
... class BikeShed:
...
...     @property
...     def max_bike_size(self):
...         return 7
...
...     @property
...     def size(self):
...         return 161
...
...     def get_capacity(self):
...         return super().get_capacity()

>>> bikeshed = BikeShed()
>>> bikeshed.get_capacity()
23

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪一个,请了解更多关于安装包的信息。

源代码发行版

本发行版没有可用的源代码发行版文件。请参阅生成发行版存档的教程。

构建发行版

abstracts-0.0.12-py3-none-any.whl (11.7 kB 查看哈希值)

上传时间 Python 3

支持者

AWSAWS云计算和安全赞助商DatadogDatadog监控FastlyFastlyCDNGoogleGoogle下载分析MicrosoftMicrosoftPSF赞助商PingdomPingdom监控SentrySentry错误日志StatusPageStatusPage状态页面