Search code examples
pythonmethodsgetattribute

call method on returned value of `__getattribute__`


I'm trying to programmatically call a particular method on attributes of a class, Outer calling the step method on the Inner attribute below. I need to do this because I'll have a variable number of attributes that implement the step method.

class Inner(object):
    def __init__(self):
        self.a = 0
    def step(self):
        self.a += 1

class Outer(object):
    def __init__(self):
        self.inner = Inner()
        self.step_attrs = []
        for attr in self.__dir__():
            if hasattr(self.__getattribute__(attr), 'step'):
                self.step_attrs.append(attr)
    def step(self):
        for attr in self.step_attrs:
            self.__getattribute__(attr).__getattribute__('step')()
        

outer = Outer()
print(outer.inner.a)
outer.step()
print(outer.inner.a)

This code throws: TypeError: expected 1 argument, got 0

If I changed the last line in the Outer().step method to

self.__getattribute__(attr).__getattribute__('step')(self.__getattribute__(attr))

it fails with TypeError: step() takes 1 positional argument but 2 were given


Solution

  • if i got you right, you need somethig like this :

    class Inner(object):
        def __init__(self):
            self.a = 0
        def step(self):
            self.a += 1
    
    class Outer(object):
        def __init__(self):
            self.inner = Inner()
            self.step_attrs = [i for i in self.__dict__ if hasattr(self,"step")]
            print(self.step_attrs)
    
        def step(self):
            for j in self.step_attrs:
                getattr(self,j).step()
    
    outer = Outer()
    print(outer.inner.a)
    outer.step()
    print(outer.inner.a)
    
    

    Result :

    ['inner']
    0
    1