例如,在Java中,@Override注释不仅提供了重写的编译时检查,而且可以生成优秀的自文档代码。
我只是在寻找文档(尽管如果它是一些检查器(如pylint)的指示器,那是额外的奖励)。我可以在某处添加注释或文档字符串,但在Python中指示重写的惯用方法是什么?
例如,在Java中,@Override注释不仅提供了重写的编译时检查,而且可以生成优秀的自文档代码。
我只是在寻找文档(尽管如果它是一些检查器(如pylint)的指示器,那是额外的奖励)。我可以在某处添加注释或文档字符串,但在Python中指示重写的惯用方法是什么?
当前回答
我创建的装饰器不仅检查覆盖属性的名称是否为该属性所在类的任何超类(无需指定超类),还检查确保覆盖属性必须与被覆盖属性的类型相同。类方法被视为方法,静态方法被视为函数。这个装饰器适用于可调用对象、类方法、静态方法和属性。
源代码见:https://github.com/fireuser909/override
此装饰器仅适用于作为重写实例的类。OverridesMeta,但是如果你的类是一个自定义元类的实例,使用create_custom_overrides_meta函数来创建一个与覆盖装饰器兼容的元类。对于测试,运行覆盖。__init__模块。
其他回答
基于这个和fwc:s的答案,我创建了一个pip可安装包https://github.com/mkorpela/overrides
我经常在这里看到这个问题。 这主要发生在(再次)在我们的代码库中看到相同的错误之后:有人在重命名“接口”中的方法时忘记了一些“接口”实现类。
好吧,Python不是Java,但Python有强大的功能——显式比隐式好——在现实世界中,有一些真实的具体案例,这个东西会帮助我。
这是overrides decorator的草图。这将检查作为参数给出的类是否与被修饰的方法具有相同的方法(或其他东西)名称。
如果你能想到一个更好的解决方案,请张贴在这里!
def overrides(interface_class):
def overrider(method):
assert(method.__name__ in dir(interface_class))
return method
return overrider
其工作原理如下:
class MySuperInterface(object):
def my_method(self):
print 'hello world!'
class ConcreteImplementer(MySuperInterface):
@overrides(MySuperInterface)
def my_method(self):
print 'hello kitty!'
如果你做了一个错误的版本,它会在类加载时引发一个断言错误:
class ConcreteFaultyImplementer(MySuperInterface):
@overrides(MySuperInterface)
def your_method(self):
print 'bye bye!'
>> AssertionError!!!!!!!
如果你只是为了文档的目的,你可以定义你自己的覆盖装饰器:
def override(f):
return f
class MyClass (BaseClass):
@override
def method(self):
pass
这实际上只是花瓶,除非你创建override(f)的方式实际上是检查重写。
但是,这是Python,为什么要写成Java呢?
在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:
...
Python不是Java。当然,没有真正的编译时检查。
我认为文档字符串中的注释就足够了。这允许您的方法的任何用户输入help(obj.method),并看到该方法是一个覆盖。
你也可以用类Foo(interface)显式地扩展一个接口,这将允许用户输入help(interface .method)来了解你的方法想要提供的功能。
就像其他人说的,不像Java,没有@Overide标签,但是上面你可以使用装饰器创建自己的,但是我建议使用getattrib()全局方法,而不是使用内部dict,这样你就会得到如下内容:
def Override(superClass):
def method(func)
getattr(superClass,method.__name__)
return method
如果你想,你可以在你自己的try catch中捕获getattr(),但我认为getattr方法在这种情况下更好。
此外,它还捕获绑定到类的所有项,包括类方法和变量