Search code examples
pythonmethodscatch-all

Catch-all method in class that passes all unknown functions to instance in class


I want to forward all of the unknown functions in my own class definition to an object in that class. One could directly access the object in the class, but was wondering if there is a pythonic way to pass all of the methods that belong to this object directly. Look at it as a 'catch-all' for methods or passthrough.

Tried getattr but failed to get it to do exactly what I want it to do.

class MyClass(): 

   def __init__(self, name, object): 
         self.name = name
         self.object = object

   def known_function(self): 
         return '{}_blabla'.format(self.name) 

   def all_unknown_functions(self): 
         return self.object.thisunknownfunction()

Want: all of the unknown functions to pass through to the object inside my class, without me having to re-define all of these functions.

edit: the getattr method would be the same as the all_unknown_functions method edit2: fixed the parameter in known_function


Solution

  • You can override __getattr__ and add your self.object search logic for missing attribute there:

    class MyClass():  
        def __init__(self, name, obj):  
            self.name = name 
            self.obj = obj 
    
        def known_function(self, name):  
            return '{}_blabla'.format(name) 
    
        def __getattr__(self, attr): 
            if attr not in self.__dict__: 
                return getattr(self.obj, attr) 
            return super().__getattr__(attr) 
                                                                                                                                                                                                        
        
    m = MyClass('foo', str)                                                                                                                                                                            
        
    m.lower                                                                                                                                                                                            
    # <method 'lower' of 'str' objects>
        
    m.known_function('spam')                                                                                                                                                                           
    # 'spam_blabla'
    

    Here we're checking if the attr is in the instance dict, if not we get the attribute from self.obj.

    Note that, this will get any attribute, not only a function. You can add a types.MethodType check later.


    Also, you've referred the name name in known_function, which does not exist in the local scope, you presumably meant to take a name argument or use self.name.


    Edit:

    Actually __getattr__ is called last in the attribute lookup chain, so you can drop the check for self.__dict__ as this check has been done earlier already, so do:

    class MyClass(): 
        def __init__(self, name, obj):  
            self.name = name 
            self.obj = obj 
        def known_function(self, name):  
            return '{}_blabla'.format(name) 
    
        def __getattr__(self, attr): 
            return getattr(self.obj, attr)