我有一个父类P
和几个子类。父类包含一个方法doSomething(x)
,只定义为:
def doSomething(self, x):
pass
现在,P
的某些子类可能已经实现了这个方法,而另一些则没有。有没有办法在运行时检查 doSomething(x)
是否仅仅是执行 pass
,例如如果它被实现了就执行它,否则跳过它?
我有一个父类P
和几个子类。父类包含一个方法doSomething(x)
,只定义为:
def doSomething(self, x):
pass
现在,P
的某些子类可能已经实现了这个方法,而另一些则没有。有没有办法在运行时检查 doSomething(x)
是否仅仅是执行 pass
,例如如果它被实现了就执行它,否则跳过它?
在这里除了调用实例上的doMethod()
方法之外,不需要进行任何操作。调用一个无操作方法并不会浪费太多资源,因此检测子类是否已经覆盖该方法并不能带来什么优势。
因此,您的第一选择是直接调用该方法,不必担心它是一个空方法。这就是pass
的作用,为您提供一个什么都不做的父类方法。
接下来,您声明:
父类包含方法
doSomething(x)
您可以使用此方法来检测您是否仍具有该方法;绑定方法的基础函数将是相同的对象:
hook = instance.doSomething
if hook.__func__ is ParentClass.doSomething:
# they didn't override the method, so nothing needs to be done.
再次强调,我不确定为什么有人想这样做,因为那个测试不会比使用instance.doSomething()
省任何东西。
接下来,一个由语句pass
组成的函数将始终编译为相同的字节码;它与return None
的字节码相同。如果您必须知道一个函数是否为空,请比较字节码:
_RETURN_NONE = (lambda: None).__code__.co_code
def is_pass(f):
return f.__code__.co_code == _RETURN_NONE
这可以应用于任何本质上只返回None
并且什么都不做的函数或方法。
演示:
>>> class P:
... def doSomething(self, x):
... pass
...
>>> class Child1(P):
... def doSomething(self, x):
... print("We are doing something with {!r}!".format(x))
...
>>> class Child2(P):
... pass
...
>>> instance1 = Child1()
>>> instance2 = Child2()
>>> instance1.doSomething(42)
We are doing something with 42!
>>> instance2.doSomething(42)
>>> instance1.doSomething.__func__ is P.doSomething
False
>>> instance2.doSomething.__func__ is P.doSomething
True
>>> is_pass(instance1.doSomething)
False
>>> is_pass(instance2.doSomething)
True
>>> def unrelated_function():
... return 42
...
>>> def another_unrelated_function():
... pass
...
>>> is_pass(unrelated_function)
False
>>> is_pass(another_unrelated_function)
True
is_pass()
适用于任何使用pass
的函数。由于您的父方法被定义为
def doSomething(x):
pass
它什么都不做 - 直接调用比验证是否被覆盖更便宜。因为它一开始就什么都不做,所以会自动“跳过”。
话虽如此,如果你真的想测试它,可以这样做:
if type(some_instance).doSomething is ParentClass.doSomething:
print('Not overriden')
else:
print('Function has been overriden, call it'):
some_instance.doSomething()
NotImplemented
,或者抛出NotImplementedError
。关于NotImplementedError
的文档还提到,如果该类永远不支持该方法,可以将该方法设置为None
。 - Patrick Haugh