检查函数是否包含通过

时间:2018-10-08 16:38:45

标签: python python-3.x class oop python-3.5

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

def doSomething(self, x):
    pass

现在,P的某些子类可能已实现此方法,而某些子类则未实现。

有什么办法可以在运行时检查doSomething(x)除了pass之外什么都不会做(例如,如果已实现,请执行,否则请跳过)?

2 个答案:

答案 0 :(得分: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()

答案 1 :(得分:1)

除了在实例上调用doMethod()之外,这里不需要做任何 。调用no-op方法的成本并不高,因此检测子类何时实现了覆盖将为您节省任何费用。

因此,您的第一选择是仅调用方法,而不必担心它是一个空方法。这就是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的任何函数上工作。