Проверка, содержит ли функция проход - PullRequest
0 голосов
/ 08 октября 2018

У меня есть один родительский класс P и несколько дочерних классов.Родительский класс содержит метод doSomething(x), определенный только как:

def doSomething(self, x):
    pass

Теперь некоторые из подклассов P могли реализовать этот метод, а некоторые - нет.Можно ли как-нибудь проверить, будет ли doSomething(x) ничего не делать, кроме pass, во время выполнения (например, если оно реализовано, выполнить его, если нет, пропустить)?

Ответы [ 2 ]

0 голосов
/ 08 октября 2018

Нет необходимости делать что-либо здесь, кроме простого вызова doMethod() для экземпляра.Вызов метода no-op не так затратен, так как обнаружение, когда дочерний класс реализует переопределение, спасет вас.

Таким образом, ваша опция номер 1 - , просто вызовите метод и не беспокойтесь, что это пустой метод.Вот что 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.

0 голосов
/ 08 октября 2018

Поскольку ваш родительский метод определен как

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