1

is there some kind of fallback function (Solidity analogy) in python? A fallback function is always called when no corresponding method is found in a class.

For example I have class A with no methods, but only a fallback function:

class A:
   def fallback(self, *args, **kwargs):
       # Somehow get the function name from kwargs
       print(f"Function {kwargs['function_name']} doesn't exist}"

So, when I call a nonexistent function I should get "Function non_existent doesn't exist", instead of AttributeError Exception.

a = A()
a.non_existent()
Mecanicul
  • 11
  • 2
  • 3
    Why do you need something like this? You can catch the `AttributeError` & handle it to get the same result – rdas Sep 26 '22 at 06:25
  • A method call in Python is actually an attribute access `obj.non_existent` followed by a call. So any solution that implements a fallback method will also provide a fallback *attribute*. Your code will keep on executing even if you typo an attribute name, which is a pretty bad idea. – BoppreH Jul 17 '23 at 11:50

1 Answers1

0

This is a solution that worked for me. The mechanism searches the objects dict in getattr and gives back a callable that forwards the call back to the original objects fallback method.

class CallMeAnything:

    class _Callable:
        def __init__(self, instance, method):
            self._instance = instance
            self._method = method

        def __call__(self, *args, **kwargs):
            # call original instance fallback method
            return self._instance._fallback_method(self._method, args, kwargs)

    def __getattr__(self, key):
        if key in self.__dict__:
            return self.__dict__[key]
        # no method or attribute found in this instance -> create fallback callable
        return CallMeAnything._Callable(self, key)

    def _fallback_method(self, method_name, args, kwargs):
        print(f"called {method_name} with args={args} and kwargs = {kwargs})")


if __name__ == "__main__":
    o = CallMeAnything()
    o.hello("world")
    o.foo(42, bar="foobar")
Jan
  • 1,359
  • 1
  • 13
  • 18