Я столкнулся с проблемами рекурсии и пытался как-то решить эту проблему pythoni c.
Лучший подход для предотвращения повторного рекурсивного вызова функции Я предпочитаю использовать декоратор, содержащий блокировку вызова внутри try /finally.
Но оба подхода моей упрощенной программы ниже не работают в классах с ссылками на себя. Сообщения об ошибках включены в виде комментариев.
class Once:
"""Decorator object approach"""
def __init__(self, func):
self._func = func
self._iscalling = False
def __call__(self, *args, **kwargs):
if self._iscalling:
print("Preventing recursive call of ", self._func)
return
try:
self._iscalling = True
print("Starting...")
return self._func(*args, **kwargs)
except Exception as e:
print(e)
finally:
print("Done.")
self._iscalling = False
class Emitter:
"""Handles functions in list and calls them all"""
def __init__(self, m: "Master"):
self.funcs = list()
self.m = m
self.running = False
def add_fnc(self, fnc):
self.funcs.append(fnc)
def once(self, old_fnc):
"""Function decorator approach"""
def new_func(*args, **kwargs):
if self.running:
print("Prevented execution!")
return
try:
self.running = True
print("Starting...")
old_fnc(*args, **kwargs)
except Exception as e:
print(e)
finally:
print("Done.")
self.running = False
return new_func
@Once # (class) run() missing 1 required positional argument: 'self'
# @once # (function) TypeError: once() missing 1 required positional argument: 'old_fnc'
def run(self):
"""This function must not run recursively"""
print("Emitting calls...")
for f in self.funcs:
f(self.m) # Calling with ref to master
print("Emitting calls done")
class Master:
def __init__(self):
self.emitter = Emitter(self)
def run(self):
self.emitter.run()
def greet(m: Master):
"""Simple ugly function causing recursion"""
print("Master greets us! Greet back.")
m.run() # Starting recursion
master = Master()
master.emitter.add_fnc(greet)
master.run()
Я также пробовал некоторые из functools
, как в примерах, но ничего не менял.
Спасибо