Home > Back-end >  Loop through functions in a Class in Python
Loop through functions in a Class in Python

Time:12-24

I have the following simplified code:

class States:
    def __init__(self):
        pass

    def state1(self):
        a = 2*10
        return a

    def state2(self):
        a = 50/10
        return a

class Results:
    def __init__(self):
        pass

    def result(self):
        states = States()
        
        x = []
        
        for i in [state1,state2]:
            state_result = states.i()
            x.append(state_result)
            
        return x

I want to loop through every function in the class "States". Of course

for i in [state1,state2]

will return "name 'state1' is not defined", but I hope it gives an idea what I try to achieve.

CodePudding user response:

You can use dir() to get the name of the functions of a class. You can then use getattr() to call the function.

class States:
    def __init__(self):
        pass

    def state1(self):
        a = 2*10
        return a

    def state2(self):
        a = 50/10
        return a

state = States()
for func in dir(States):
    if func.startswith('__'):
        continue
    print(func)
    print(getattr(state, func)())

Will output

state1
20
state2
5.0

CodePudding user response:

You can do this tho:

def result(self):
        states = States()
        
        x = []
        
        for i in [states.state1,states.state2]: # changed state1 to states.state1 and so on
            state_result = i()
            x.append(state_result)
            
        return x

CodePudding user response:

I think you can use lambda. Here, i made a simple example for you.

def foo(text):
    print(text)
        
            
a = [lambda: foo("hey"), lambda: foo("boo")]
for i in a:
    i()

Result:

hey
boo

In your case, you should come over with this:

for i in [lambda: state1(), lambda:state2()]:
    state_result = i()
    x.append(state_result)

But if you ask my opinion, it's important to inform you that calling functions through a list is not a healthy way. A software languge usually has a solution for many cases; but in this case, i think your point of view is wrong. Doing work by messing with built-in techniques and trying to find some secret tricks is is not a suggested thing.

CodePudding user response:

You can get the members of class States via the class' dict as:

States.__dict__

Which'll give you all the attributes and function of your class as:

{'__module__': '__main__', '__init__': <function States.__init__ at 0x00000183066F0A60>, 'state1': <function States.state1 at 0x00000183066F0AF0>, 'state2': <function States.state2 at 0x000001830 ...

You can filter this into a list comprehension dict to not include dunders as:

[funcname for funcname in States.__dict__ if not (str.startswith('__') and str.endswith('__'))]

This will return you a list of member functions as:

['state1', 'state2']

Then create an object of States as:

states = States()

get the whole calculation done as:

for funcname in [funcname for funcname in States.__dict__ if not (funcname.startswith('__') and funcname.endswith('__'))]:
    x.append(States.__dict__[funcname](states))

Better yet, make it a comprehension as:

[States.__dict__[funcname](states) for funcname in States.__dict__ if not (funcname.startswith('__') and funcname.endswith('__'))]

Your answer after applying this approach is: [20, 5.0]

CodePudding user response:

The clean way to do this is to "register" your state methods. SOmething like this:

class States():
    states = []
    def register_state(cache):
        def inner(fn):
            cache.append(fn)
        return inner
    
    @register_state(states)
    def state1(self):
        a = 2*10
        return a
        
    @register_state(states)
    def state2(self):
        a = 50/10
        return a

Then your Results class can do

class Results:
    def __init__(self):
        pass
    
    def result(self):
        states = States()
        
        x = []
        
        for i in states.states:
            state_result = i(states)
            x.append(state_result)
            
        return x
  • Related