例如,在Java中,@Override注释不仅提供了重写的编译时检查,而且可以生成优秀的自文档代码。

我只是在寻找文档(尽管如果它是一些检查器(如pylint)的指示器,那是额外的奖励)。我可以在某处添加注释或文档字符串,但在Python中指示重写的惯用方法是什么?


当前回答

如果你只是为了文档的目的,你可以定义你自己的覆盖装饰器:

def override(f):
    return f


class MyClass (BaseClass):

    @override
    def method(self):
        pass

这实际上只是花瓶,除非你创建override(f)的方式实际上是检查重写。

但是,这是Python,为什么要写成Java呢?

其他回答

基于这个和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:
        ...

Hear是最简单的,可以在Jython下使用Java类:

class MyClass(SomeJavaClass):
     def __init__(self):
         setattr(self, "name_of_method_to_override", __method_override__)

     def __method_override__(self, some_args):
         some_thing_to_do()

Python不是Java。当然,没有真正的编译时检查。

我认为文档字符串中的注释就足够了。这允许您的方法的任何用户输入help(obj.method),并看到该方法是一个覆盖。

你也可以用类Foo(interface)显式地扩展一个接口,这将允许用户输入help(interface .method)来了解你的方法想要提供的功能。