在Java中,例如, @Override
注释不仅提供了编译时的覆盖的检查,但使优秀自记录代码。
我只是在寻找文件(尽管如果它像pylint的一些检查的指标,这是一个奖金)。 我可以添加注释或文档字符串的地方,但什么是惯用的方法来指示在Python的覆盖?
在Java中,例如, @Override
注释不仅提供了编译时的覆盖的检查,但使优秀自记录代码。
我只是在寻找文件(尽管如果它像pylint的一些检查的指标,这是一个奖金)。 我可以添加注释或文档字符串的地方,但什么是惯用的方法来指示在Python的覆盖?
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!!!!!!!
下面是一个不需要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
如果你只是想为这个文件的目的,你可以定义自己的覆盖装饰:
def override(f):
return f
class MyClass (BaseClass):
@override
def method(self):
pass
这是真的只是养眼,除非你以这样的方式,实际上是检查的覆盖创建覆盖(F)。
不过,这是Python的,为什么要写它喜欢它的Java?
Python是不是Java。 有,当然没有这样的事情真的像编译时检查。
我想在文档字符串评论充足。 这使您的方法类型的任何用户help(obj.method)
看到了该方法的重写。
您也可以明确地扩展与接口class Foo(Interface)
,这将允许用户键入help(Interface.method)
获得有关你的方法旨在提供的功能的想法。
像其他人不同的Java说,没有@Overide标签上方。然而你却可以创建自己使用的装饰让你得到像下面我会建议使用getattrib()全局法,而不是使用内部字典:
def Override(superClass):
def method(func)
getattr(superClass,method.__name__)
return method
如果你想,你可以赶上GETATTR()在自己的尝试捕捉提高自己的错误,但我认为GETATTR方法是在这种情况下更好。
另外这款捕捉绑定到一个类中的所有物品,包括类的方法和vairables
即兴的@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
错误越早抓获。
根据@ mkorpela最伟大的答案,我写了一个类似的包(ipromise 的PyPI github上 ),做更多的检查:
假设A选自B继承和C.和早餐继承C. ipromise会检查
如果房颤覆盖了Bf,BF必须存在,并且A必须从B.继承(这是从覆盖包检查)。
您没有房颤宣布,它将覆盖BF,然后宣布,它将覆盖CF A应该说,它比照覆盖,因为B可能决定停止重写此方法的模式,而不应导致下游更新。
您没有房颤宣布,它将覆盖比照格局,但详细的展望没有声明其覆盖。
您没有房颤宣布,它将覆盖比照模式,但详细的展望声明,它从某DF覆盖
它也有一个标记,并检查执行一个抽象方法的各种特征。
听到的是最简单和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()