例如,在Java中,@Override注释不仅提供了重写的编译时检查,而且可以生成优秀的自文档代码。
我只是在寻找文档(尽管如果它是一些检查器(如pylint)的指示器,那是额外的奖励)。我可以在某处添加注释或文档字符串,但在Python中指示重写的惯用方法是什么?
例如,在Java中,@Override注释不仅提供了重写的编译时检查,而且可以生成优秀的自文档代码。
我只是在寻找文档(尽管如果它是一些检查器(如pylint)的指示器,那是额外的奖励)。我可以在某处添加注释或文档字符串,但在Python中指示重写的惯用方法是什么?
当前回答
基于@mkorpela的精彩回答,我写了一个类似的包(ipromise pypi github),它做了更多的检查:
假设A继承了B和C, B继承了C。
模块ipromise检查:
If A.f overrides B.f, B.f must exist, and A must inherit from B. (This is the check from the overrides package). You don't have the pattern A.f declares that it overrides B.f, which then declares that it overrides C.f. A should say that it overrides from C.f since B might decide to stop overriding this method, and that should not result in downstream updates. You don't have the pattern A.f declares that it overrides C.f, but B.f does not declare its override. You don't have the pattern A.f declares that it overrides C.f, but B.f declares that it overrides from some D.f.
它还具有用于标记和检查实现抽象方法的各种特性。
其他回答
在python 3.6及以上版本中,@override提供的功能可以使用python的描述符协议轻松实现,即set_name dunder方法:
class override:
def __init__(self, func):
self._func = func
update_wrapper(self, func)
def __get__(self, obj, obj_type):
if obj is None:
return self
return self._func
def __set_name__(self, obj_type, name):
self.validate_override(obj_type, name)
def validate_override(self, obj_type, name):
for parent in obj_type.__bases__:
func = parent.__dict__.get(name, None)
if callable(func):
return
else:
raise NotImplementedError(f"{obj_type.__name__} does not override {name}")
注意,这里的set_name是在定义包装类之后调用的,我们可以通过调用包装类的dunder方法基来获得它的父类。
对于它的父类,我们希望检查包装的函数是否在类中通过实现
检查函数名是否在类字典中 它是可调用的
使用i就像这样简单:
class AbstractShoppingCartService:
def add_item(self, request: AddItemRequest) -> Cart:
...
class ShoppingCartService(AbstractShoppingCartService):
@override
def add_item(self, request: AddItemRequest) -> Cart:
...
如果你只是为了文档的目的,你可以定义你自己的覆盖装饰器:
def override(f):
return f
class MyClass (BaseClass):
@override
def method(self):
pass
这实际上只是花瓶,除非你创建override(f)的方式实际上是检查重写。
但是,这是Python,为什么要写成Java呢?
Python不是Java。当然,没有真正的编译时检查。
我认为文档字符串中的注释就足够了。这允许您的方法的任何用户输入help(obj.method),并看到该方法是一个覆盖。
你也可以用类Foo(interface)显式地扩展一个接口,这将允许用户输入help(interface .method)来了解你的方法想要提供的功能。
我创建的装饰器不仅检查覆盖属性的名称是否为该属性所在类的任何超类(无需指定超类),还检查确保覆盖属性必须与被覆盖属性的类型相同。类方法被视为方法,静态方法被视为函数。这个装饰器适用于可调用对象、类方法、静态方法和属性。
源代码见:https://github.com/fireuser909/override
此装饰器仅适用于作为重写实例的类。OverridesMeta,但是如果你的类是一个自定义元类的实例,使用create_custom_overrides_meta函数来创建一个与覆盖装饰器兼容的元类。对于测试,运行覆盖。__init__模块。
基于@mkorpela的精彩回答,我写了一个类似的包(ipromise pypi github),它做了更多的检查:
假设A继承了B和C, B继承了C。
模块ipromise检查:
If A.f overrides B.f, B.f must exist, and A must inherit from B. (This is the check from the overrides package). You don't have the pattern A.f declares that it overrides B.f, which then declares that it overrides C.f. A should say that it overrides from C.f since B might decide to stop overriding this method, and that should not result in downstream updates. You don't have the pattern A.f declares that it overrides C.f, but B.f does not declare its override. You don't have the pattern A.f declares that it overrides C.f, but B.f declares that it overrides from some D.f.
它还具有用于标记和检查实现抽象方法的各种特性。