检查函数是否包含 pass 关键字

3

我有一个父类P和几个子类。父类包含一个方法doSomething(x),只定义为:

def doSomething(self, x):
    pass

现在,P 的某些子类可能已经实现了这个方法,而另一些则没有。有没有办法在运行时检查 doSomething(x) 是否仅仅是执行 pass,例如如果它被实现了就执行它,否则跳过它?


2
为什么跳过它?它什么都不做,所以为什么要费心呢? - Martijn Pieters
1
而且ABC模块也无法帮助您检测空操作方法。 - Martijn Pieters
你可以返回NotImplemented,或者抛出NotImplementedError。关于NotImplementedError的文档还提到,如果该类永远不支持该方法,可以将该方法设置为None - Patrick Haugh
2个回答

3

在这里除了调用实例上的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的函数。

2

由于您的父方法被定义为

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接