在Python中,我如何表示重写一个方法?

例如,在Java中,@Override注解不仅提供了覆盖的编译时检查,而且还提供了优秀的自写文档代码。 我只是在寻找文档(虽然如果它是像pylint这样的检查器的指标,这是一个奖金)。 我可以在某处添加注释或文档string,但是在Python中指示覆盖的惯用方法是什么?

更新(23.05.2015):基于这个和fwc:s的答案我创build了一个点可安装包https://github.com/mkorpela/overrides

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

那么Python不是Java,但是Python有力量,而且显式比隐式更好 – 在现实世界中,真实的具体事例会帮助我。

所以这里是覆盖装饰器的草图。 这将检查作为参数给出的类与正在装饰的方法具有相同的方法(或其他)名称。

如果您能想到更好的解决scheme,请在此发布!

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

这是一个不需要指定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 

Python不是Java。 编译时检查当然不会有这样的事情。

我认为在文档中的评论是很多的。 这允许您的方法的任何用户键入help(obj.method)并看到该方法是一个覆盖。

您还可以使用class Foo(Interface)显式扩展class Foo(Interface) ,这将允许用户inputhelp(Interface.method)来获得您的方法打算提供的function。

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

 def override(f): return f class MyClass (BaseClass): @override def method(self): pass 

这真的不过是眼花缭乱,除非你以这种方式创build覆盖(f),实际上是检查覆盖。

但是,这是Python,为什么要像Java那样写呢?

据我所知,在Python中没有特别的方式来表示重写。 您只需定义方法并像往常一样包含文档string。

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

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

如果你想在你自己的尝试catch中捕获getattr()引发你自己的错误,但是我认为getattr方法在这种情况下更好。

此外,这捕获所有绑定到一个类的项目,包括类方法和可变参数

听起来很简单,在Java类的Jython下工作:

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