【问题标题】:Checking whether function contains pass检查函数是否包含 pass
【发布时间】:2019-03-13 09:13:30
【问题描述】:

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

def doSomething(self, x):
    pass

现在,P 的一些子类可能已经实现了这个方法,而有些则没有。有什么方法可以检查doSomething(x) 在运行时是否除了pass 之外什么都不做(例如,如果已实现,则执行它,如果没有,则跳过它)?

【问题讨论】:

  • 为什么要跳过它?它什么都不做,何必呢?
  • 而且 ABC 模块也无法帮助您检测空操作方法。
  • 您可以改为返回NotImplemented,或提出NotImplementedErrorNotImplementedError 的文档还提到将方法设置为 None,如果该类永远不会支持该方法。

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


【解决方案1】:

因为你的父方法被定义为

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-21
      • 1970-01-01
      • 1970-01-01
      • 2012-03-27
      • 2019-08-10
      • 2021-05-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多