一个装饰器,用于自动检测覆盖方法时出现的差异。
项目描述
一个装饰器 @override,用于验证应覆盖继承方法的方法实际上是否进行了覆盖。
将继承方法的文档字符串复制到覆盖方法。
由于签名验证和文档字符串继承是在类创建时而不是在类实例化时执行的,因此此库在显著影响性能的同时,显著提高了创建Python类层次结构的安全性和用户体验。请参阅https://stackoverflow.com/q/1167617以了解此库的初始灵感。
动机
Python没有标准机制来保证(1)之前覆盖了继承方法的方法继续这样做,以及(2)之前没有覆盖继承方法的方法现在不会覆盖。这为随着时间的推移而演变的类层次结构打开了微妙的问题的大门。例如,
添加到超类中的方法被子类中同名的现有方法所屏蔽。
被子类覆盖的超类方法在超类中被重命名,但在子类中没有。
在父类中被子类覆盖的方法在父类中被删除,但在子类中没有删除。
父类中被子类覆盖的方法,但其签名与继承的方法不兼容。
这些情况只能通过在代码中显式标记方法覆盖来检查。
Python 也没有继承覆盖方法文档字符串的标准机制。因为大多数标准代码检查器(例如 flake8)都有要求所有公共方法必须有文档字符串的规则,这不可避免地导致在覆盖方法上出现大量“参见父类使用方法”的文档字符串,或者更糟糕的是,完全禁用这些规则。此外,平庸或缺失的文档字符串会降低编辑器提供的工具提示和自动完成的品质。
安装
兼容 Python 3.6+。
$ pip install overrides
使用方法
使用 @override 来指示子类方法应该覆盖父类方法。
from overrides import override
class SuperClass:
def foo(self):
"""This docstring will be inherited by any method that overrides this!"""
return 1
def bar(self, x) -> str:
return x
class SubClass(SuperClass):
@override
def foo(self):
return 2
@override
def bar(self, y) -> int: # Raises, because the signature is not compatible.
return y
@override
def zoo(self): # Raises, because does not exist in the super class.
return "foobarzoo"
使用 EnforceOverrides 来要求覆盖父类方法的子类方法必须使用 @override 装饰。
from overrides import EnforceOverrides
class SuperClass(EnforceOverrides):
def foo(self):
return 1
class SubClass(SuperClass):
def foo(self): # Raises, because @override is missing.
return 2
使用 @final 来指示父类方法不能被覆盖。在 Python 3.11 及以上版本中,@final 可以直接使用 typing.final。
from overrides import EnforceOverrides, final, override
class SuperClass(EnforceOverrides):
@final
def foo(self):
return 1
class SubClass(SuperClass):
@override
def foo(self): # Raises, because overriding a final method is forbidden.
return 2
请注意,必须在 @override 前声明 @classmethod 和 @staticmethod。
from overrides import override
class SuperClass:
@staticmethod
def foo(x):
return 1
class SubClass(SuperClass):
@staticmethod
@override
def foo(x):
return 2
控制标志
# To prevent all signature checks do:
@override(check_signature=False)
def some_method(self, now_this_can_be_funny_and_wrong: str, what_ever: int) -> "Dictirux":
pass
# To do the check only at runtime and solve some forward reference problems
@override(check_at_runtime=True)
def some_other_method(self, ..) -> "SomethingDefinedLater":
pass
a.some_other_method() # Kaboom if not SomethingDefinedLater
贡献者
本项目的存在仅通过所有贡献者的工作实现。
mkorpela, drorasaf, ngoodman90, TylerYep, leeopop, donpatrice, jayvdb, joelgrus, lisyarus, soulmerge, rkr-at-dbx, ashwin153, brentyi, jobh, tjsmart, bersbersbers, LysanderGG, mgorny。
项目详情
下载文件
下载适合您平台的应用程序。如果您不确定要选择哪一个,请了解更多关于 安装包的信息。