在Python,我怎么表示我重写的方法?(In Python, how do I indicate

2019-06-26 13:30发布

在Java中,例如, @Override注释不仅提供了编译时的覆盖的检查,但使优秀自记录代码。

我只是在寻找文件(尽管如果它像pylint的一些检查的指标,这是一个奖金)。 我可以添加注释或文档字符串的地方,但什么是惯用的方法来指示在Python的覆盖?

Answer 1:

UPDATE(2015年5月23日):在此基础上与FWC:的答案我创建了一个点子安装的软件包https://github.com/mkorpela/overrides

时不时我会在这里结束看这个问题。 主要发生这种情况后(再次)看到我们的代码库相同的错误:有人已经忘记了一些“接口”实现类,而重命名中的“接口”的方法..

那么Python是不是Java,但是Python有力量 - 和明确优于隐式 - 也有真正的具体案例在现实世界里,这个东西会帮助我。

因此,这里是覆盖装饰的草图。 这将检查作为参数的类具有相同的方法(或东西)的名称作为方法的装饰。

如果你能想到一个更好的解决方案请在这里发表吧!

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!!!!!!!


Answer 2:

下面是一个不需要interface_class名称的规范的实施。

import inspect
import re

def overrides(method):
    # actually can't do this because a method is really just a function while inside a class def'n  
    #assert(inspect.ismethod(method))

    stack = inspect.stack()
    base_classes = re.search(r'class.+\((.+)\)\s*\:', stack[2][4][0]).group(1)

    # handle multiple inheritance
    base_classes = [s.strip() for s in base_classes.split(',')]
    if not base_classes:
        raise ValueError('overrides decorator: unable to determine base class') 

    # stack[0]=overrides, stack[1]=inside class def'n, stack[2]=outside class def'n
    derived_class_locals = stack[2][0].f_locals

    # replace each class name in base_classes with the actual class type
    for i, base_class in enumerate(base_classes):

        if '.' not in base_class:
            base_classes[i] = derived_class_locals[base_class]

        else:
            components = base_class.split('.')

            # obj is either a module or a class
            obj = derived_class_locals[components[0]]

            for c in components[1:]:
                assert(inspect.ismodule(obj) or inspect.isclass(obj))
                obj = getattr(obj, c)

            base_classes[i] = obj


    assert( any( hasattr(cls, method.__name__) for cls in base_classes ) )
    return method


Answer 3:

如果你只是想为这个文件的目的,你可以定义自己的覆盖装饰:

def override(f):
    return f


class MyClass (BaseClass):

    @override
    def method(self):
        pass

这是真的只是养眼,除非你以这样的方式,实际上是检查的覆盖创建覆盖(F)。

不过,这是Python的,为什么要写它喜欢它的Java?



Answer 4:

Python是不是Java。 有,当然没有这样的事情真的像编译时检查。

我想在文档字符串评论充足。 这使您的方法类型的任何用户help(obj.method)看到了该方法的重写。

您也可以明确地扩展与接口class Foo(Interface) ,这将允许用户键入help(Interface.method)获得有关你的方法旨在提供的功能的想法。



Answer 5:

像其他人不同的Java说,没有@Overide标签上方。然而你却可以创建自己使用的装饰让你得到像下面我会建议使用getattrib()全局法,而不是使用内部字典:

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

如果你想,你可以赶上GETATTR()在自己的尝试捕捉提高自己的错误,但我认为GETATTR方法是在这种情况下更好。

另外这款捕捉绑定到一个类中的所有物品,包括类的方法和vairables



Answer 6:

即兴的@mkorpela 伟大的答案 ,这里是一个版本

更精确的检查,命名,并提出了错误的对象

def overrides(interface_class):
    """
    Function override annotation.
    Corollary to @abc.abstractmethod where the override is not of an
    abstractmethod.
    Modified from answer https://stackoverflow.com/a/8313042/471376
    """
    def confirm_override(method):
        if method.__name__ not in dir(interface_class):
            raise NotImplementedError('function "%s" is an @override but that'
                                      ' function is not implemented in base'
                                      ' class %s'
                                      % (method.__name__,
                                         interface_class)
                                      )

        def func():
            pass

        attr = getattr(interface_class, method.__name__)
        if type(attr) is not type(func):
            raise NotImplementedError('function "%s" is an @override'
                                      ' but that is implemented as type %s'
                                      ' in base class %s, expected implemented'
                                      ' type %s'
                                      % (method.__name__,
                                         type(attr),
                                         interface_class,
                                         type(func))
                                      )
        return method
    return confirm_override


这里是什么样子的做法:

NotImplementedError不是在基类中实现

class A(object):
    # ERROR: `a` is not a implemented!
    pass

class B(A):
    @overrides(A)
    def a(self):
        pass

结果在更具描述NotImplementedError错误

function "a" is an @override but that function is not implemented in base class <class '__main__.A'>

全栈

Traceback (most recent call last):
  …
  File "C:/Users/user1/project.py", line 135, in <module>
    class B(A):
  File "C:/Users/user1/project.py", line 136, in B
    @overrides(A)
  File "C:/Users/user1/project.py", line 110, in confirm_override
    interface_class)
NotImplementedError: function "a" is an @override but that function is not implemented in base class <class '__main__.A'>


NotImplementedError有望实现型

class A(object):
    # ERROR: `a` is not a function!
    a = ''

class B(A):
    @overrides(A)
    def a(self):
        pass

结果在更具描述NotImplementedError错误

function "a" is an @override but that is implemented as type <class 'str'> in base class <class '__main__.A'>, expected implemented type <class 'function'>

全栈

Traceback (most recent call last):
  …
  File "C:/Users/user1/project.py", line 135, in <module>
    class B(A):
  File "C:/Users/user1/project.py", line 136, in B
    @overrides(A)
  File "C:/Users/user1/project.py", line 125, in confirm_override
    type(func))
NotImplementedError: function "a" is an @override but that is implemented as type <class 'str'> in base class <class '__main__.A'>, expected implemented type <class 'function'>




关于@mkorpela答案伟大的事情是在一些初始化阶段的检查情况。 检测并不需要“跑”。 参照以前的例子中, class B是从来没有初始化( B()但该NotImplementedError仍会提高。 这意味着overrides错误越早抓获。



Answer 7:

根据@ mkorpela最伟大的答案,我写了一个类似的包(ipromise 的PyPI github上 ),做更多的检查:

假设A选自B继承和C.和早餐继承C. ipromise会检查

  • 如果房颤覆盖了Bf,BF必须存在,并且A必须从B.继承(这是从覆盖包检查)。

  • 您没有房颤宣布,它将覆盖BF,然后宣布,它将覆盖CF A应该说,它比照覆盖,因为B可能决定停止重写此方法的模式,而不应导致下游更新。

  • 您没有房颤宣布,它将覆盖比照格局,但详细的展望没有声明其覆盖。

  • 您没有房颤宣布,它将覆盖比照模式,但详细的展望声明,它从某DF覆盖

它也有一个标记,并检查执行一个抽象方法的各种特征。



Answer 8:

听到的是最简单和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()


文章来源: In Python, how do I indicate I'm overriding a method?