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

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


当前回答

就像其他人说的,不像Java,没有@Overide标签,但是上面你可以使用装饰器创建自己的,但是我建议使用getattrib()全局方法,而不是使用内部dict,这样你就会得到如下内容:

def Override(superClass):
    def method(func)
        getattr(superClass,method.__name__)
    return method

如果你想,你可以在你自己的try catch中捕获getattr(),但我认为getattr方法在这种情况下更好。

此外,它还捕获绑定到类的所有项,包括类方法和变量

其他回答

基于这个和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呢?

您可以使用来自PEP 544的协议。使用这种方法,接口实现关系只在使用站点声明。

假设您已经有了一个实现(让我们称之为MyFoobar),您定义了一个接口(一个协议),它具有实现的所有方法和字段的签名,我们称之为IFoobar。

Then, at the use site, you declare the implementation instance binding to have the interface type e.g. myFoobar: IFoobar = MyFoobar(). Now, if you use a field/method that is missing in the interface, Mypy will complain at the use site (even if it would work at runtime!). If you failed to implement a method from the interface in the implementation, Mypy will also complain. Mypy won't complain if you implement something that doesn't exist in the interface. But that case is rare, since the interface definition is compact and easy to review. You wouldn't be able to actually use that code, since Mypy would complain.

现在,这还不包括在父类和实现类中都有实现的情况,比如ABC的一些使用。但是在Java中使用override,即使在接口中没有实现。这个解决方案适用于这种情况。

from typing import Protocol

class A(Protocol):
    def b(self):
        ...
    def d(self):  # we forgot to implement this in C
        ...

class C:
    def b(self):
        return 0

bob: A = C()

输入检查结果:

test.py:13: error: Incompatible types in assignment (expression has type "C", variable has type "A")
test.py:13: note: 'C' is missing following 'A' protocol member:
test.py:13: note:     d
Found 1 error in 1 file (checked 1 source file)

基于@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.

它还具有用于标记和检查实现抽象方法的各种特性。

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()