Apr-25-2021, 07:28 AM
(This post was last modified: Apr-25-2021, 07:28 AM by Gribouillis.)
I have a solution using a function object type from my personal library, the below class 'algorithm'
# algorithm/__init__.py __version__ = '2019.06.18' from functools import partial, singledispatch import types #======================================== # Obtention de la documentation #======================================== def doctopic_assembly(): """Returns a assembly of documentation topics for this module""" from .doc.main import doctopic_assembly return doctopic_assembly() _property = property @singledispatch def property(func): return _property(func) class algorithm_meta(type): def __new__(meta, class_name, bases, new_attrs): cls = type.__new__(meta, class_name, bases, new_attrs) return cls def __call__(cls, *args, **kwargs): instance = cls.__new__(cls) instance.kwargs = kwargs instance.__dict__.update(kwargs) return instance.run(*args) #try: #return instance.run(*args) #except TypeError: #print(instance, args) #raise def __get__(cls, obj, objtype=None): # This allows to use the algoritm type as a method if obj is None: return cls return partial(_algorithm_as_method, cls, obj) property = staticmethod(property) def _algorithm_as_method(cls, obj, *args, **kwargs): instance = cls.__new__(cls) instance.o = obj instance.kwargs = kwargs instance.__dict__.update(kwargs) return instance.run(*args) @property.register(algorithm_meta) def _(cls): return _property(partial(_algorithm_as_method, cls)) class algorithm(metaclass=algorithm_meta): def run(self, *args): return selfTo implement the desired behaviour, I now define a subclass 'returnable' of 'algorithm', then I'm ready to implement your tasks B() and A(). Look at the code starting from 'class B(returnable)'
# paillasse/pf/deepreturn.py - example code from algorithm import algorithm class Return(Exception): pass class returnable(algorithm): def run(self, *args): try: return self.main(*args) except Return as exc: if exc.args[0] is self: return exc.args[1] else: raise def return_(self, value=None): raise Return(self, value) class B(returnable): def main(self, x): self.subtask0(x) self.subtask1(x) def subtask0(self, x): if x == 0: self.return_('Hello!') def subtask1(self, x): if x == 1: self.return_('World!') def A(): print(B(0)) print(B(1)) print(B(2)) if __name__ == '__main__': A()My output
Output:λ python paillasse/pf/deepreturn.py
Hello!
World!
None
By the way, it seems that the ability to return from any subtask is a nice improvement of the algorithm class. I'm considering incorporating this feature in the library. The main drawback I see is that the code is less explicit because something that looks like a function call may actually be a return statement.