蟒蛇接口

implements的Python项目详细描述


Build StatusDocumentation StatusPyPI Version

使用decorators的pythonic接口

安装

在pypi上提供了实现,可以使用pip

pip install implements

注意:python 3.5+是必需的,因为它依赖于inspect模块的新特性。

优点

  1. Favor composition over inheritance
  2. 从多个类继承可能会有问题,特别是当超类具有相同的方法名但不同的签名时。如果发生这种情况以确保契约的完整性,则实现将抛出一个描述性错误。
  3. 在导入时计算装饰器。当一个对象被实例化或一个方法被调用时,任何错误都会被引发。
  4. 比较干净。使用decorators可以清楚地表明我们想要共享行为。此外,不允许重命名参数。
  5. 代码库很小:你可以把文件复制过来这种回购存在更多的测试覆盖率。

用法

fromimplementsimportInterface,implementsclassDuck:def__init__(self,age):self.age=ageclassFlyable(Interface):@staticmethoddefmigrate(direction):passdeffly(self)->str:passclassQuackable(Interface):deffly(self)->bool:passdefquack(self):pass@implements(Flyable)@implements(Quackable)classMallardDuck(Duck):def__init__(self,age):super(MallardDuck,self).__init__(age)defmigrate(self,dir):returnTruedeffly(self):pass

上述操作将引发以下错误:

NotImplementedError:'MallardDuck'mustimplementmethod'fly((self) -> bool)'definedininterface'Quackable'NotImplementedError:'MallardDuck'mustimplementmethod'quack((self))'definedininterface'Quackable'NotImplementedError:'MallardDuck'mustimplementmethod'migrate((direction))'definedininterface'Flyable'

您可以在example.pytests.py中找到更详细的示例。

对齐

目前有两种惯用的方法重写上述示例

第一种方法是用MIXIN写基类,在每种方法中增加^ {TT3}$。

classDuck:def__init__(self,age):self.age=ageclassFlyable:@staticmethoddefmigrate(direction):raiseNotImplementedError("Flyable is an abstract class")deffly(self)->str:raiseNotImplementedError("Flyable is an abstract class")classQuackable:deffly(self)->bool:raiseNotImplementedError("Quackable is an abstract class")defquack(self):raiseNotImplementedError("Quackable is an abstract class")classMallardDuck(Duck,Quackable,Flyable):def__init__(self,age):super(MallardDuck,self).__init__(age)defmigrate(self,dir):returnTruedeffly(self):pass

但以这种方式实现它有几个缺点:

  1. 当调用quack时,我们只会得到一个NotImplementedError,这可能在运行时的稍后时间发生而且,到处筹集NotImplementedError看起来很笨拙。
  2. 如果不检查调用super的每个父类,就不清楚了。
  3. 类似地,FlyableQuackable中的fly的返回类型也不同。不熟悉python的人必须阅读Method Resolution Order
  4. MallardDuck的编写器使方法migrate成为实例方法,并将参数重命名为dir,这令人困惑
  5. 我们真的想区分行为和遗传。

使用implements的好处是它看起来更干净,并且您将在导入时而不是在实际调用方法时获得错误

另一种方法是使用内置abc模块中的抽象基类:

fromabcimportABCMeta,abstractmethod,abstractstaticmethodclassDuck(metaclass=ABCMeta):def__init__(self,age):self.age=ageclassFlyable(metaclass=ABCMeta):@abstractstaticmethoddefmigrate(direction):pass@abstractmethoddeffly(self)->str:passclassQuackable(metaclass=ABCMeta):@abstractmethoddeffly(self)->bool:pass@abstractmethoddefquack(self):passclassMallardDuck(Duck,Quackable,Flyable):def__init__(self,age):super(MallardDuck,self).__init__(age)defmigrate(self,dir):returnTruedeffly(self):pass

使用抽象基类的好处是可以更早地抛出错误 在实例化时,如果方法没有实现;还有静态分析 如果两个方法具有不同的签名,则发出警告的工具。但这解决不了 问题2-4和实现将在导入中更早地抛出错误。 在我看来,这也不像是Python。

学分

实现的灵感来自于@elifer的一个PR

测试

运行单元测试:

make test

运行皮棉:

make lint

运行毒性:

make test-all

许可证

麻省理工学院

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
JavaPax考试:从非标准Maven存储库解析Karaf特性存储库(XML文件)   java Spring启动Bean创建异常   java中将ArrayList转换为数组的方法   Android Studio的java Unity插件。   java在CheckStyle中从方法计数中排除getter和setter   HibernateJava。sql。SQLSyntaxErrorException:表/视图“序列”不存在   与命令行程序Java vs C通信   java WebView膨胀异常   java在O(n)java8流中寻找两个列表的交集   java使用Gradle运行单元测试时,最大堆大小在哪里设置?   ssl加载java应用程序(CXF)内的jks文件   CI:Jenkins Git:Simple Java项目:希望在特定时间在脚本上发送消息   java根据位置更改数字   java按数值排序字符串数组   macos java版本“1.6.0_65”是否与java 6模棱两可?   Cassandra中的java时间戳