1

Let's say I have a class like this:

class calculations():
    def __init__(self,x,y):
        self.x = x
        self.y = y

    def calc_sum(self):
        return self.x+self.y

    def calc_dif(self):
        return self.x-self.y

I was wondering, can I somehow loop through methods in a class in a for loop? For example if I input 10 and 10 it would return both calc_sum and calc_dif.

I've tried like so:

for item in calculations(10,10):
    print(item)

TypeError: 'calculations' object is not iterable

And I would expect 20 and 0.

Does that mean that classes are not iterable or is there a way to iter through them?

UPDATE

When I run:

for item in list(dir(calculations)[-2:]):
    print(item)

I get

calc_dif
calc_sum

And now I want to pass 10 and 10 to both of these methods and instead of getting the names of the methods to get the results they return. I now understand that this is not a good practice but I am just curious how would I achieve this.

Jonas Palačionis
  • 4,591
  • 4
  • 22
  • 55
  • Are you aware of [the builtin ``dir`` function](https://docs.python.org/3/library/functions.html#dir)? Note that iterating through *all* methods is rarely a good idea – for example, you likely do not want to call ``__init__`` again. – MisterMiyagi Jun 12 '20 at 08:33
  • No, I have not used `class` that much when I code but I want to start programming in an OO way, though, I am not sure if that is what people in a data science field used that often. Could you elaborate on why would iterating all methods is rarely a good idea? Also is there a way on iteratin through everything but the `__init__`?Thank you. – Jonas Palačionis Jun 12 '20 at 08:35
  • 2
    Iterating through all methods is usually not a good idea because many methods should only be called intentionally – for example, ``__init__``. However, ``__init__`` is *not the only method to exclude*, and depending on your class only you can say which methods are safe and which are not. – MisterMiyagi Jun 12 '20 at 08:38
  • So to conclude, there is a way to iter methods in a class, though it's not a good practice. I am just curious of a way I would achieve it. – Jonas Palačionis Jun 12 '20 at 08:58

2 Answers2

1

I think what you want is the following:

class calculations():

    a = 'attribute'

    def __init__(self,x,y):
        self.x = x
        self.y = y

    def calc_sum(self):
        return self.x+self.y

    def calc_dif(self):
        return self.x-self.y

# init the instance
c = calculations(5,5)

# list of methods which names do not start with '__'
methods = [getattr(calculations, m) for m in dir(calculations) if callable(getattr(calculations, m)) and not m.startswith('__')]


for m in methods:
    print(m(c))

Output:

10  # calc_sum
0   # calc_dif

Function getattr() returns the method of a class given the methods' name as a string and by using callable() you make sure that you only get methods, since dir() returns both methods and attributes:

>>> dir(calculations)
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'a',
 'calc_dif',
 'calc_sum']

Also check this question: How do I get list of methods in a Python class?

Grintas
  • 46
  • 1
  • 5
0

What should the result be? You declared class static methods (no self, nor cls in it) that take new parameters to create a new result - they do not depend on whatever you initted your instance with.

You can switch your code to:

class calculations():
    def __init__(self,x,y):
        self.x = x
        self.y = y

    def calc_sum(self):
        return self.x+self.y

    def calc_dif(self):
        return self.x-self.y

# list the methods you are interested in        
m = [calculations.calc_sum, calculations.calc_dif] 

# init the instance
c = calculations(5,5)

# call each method on the instance:
for f in m:
    print(f (c))

Output:

10  # calc_sum
0   # calc_dif

Readup:

Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
  • Thank you. Is there a way to get your output without hardcoding the methods in a list? Like to say 'for every method in a class return all of the methods defined in a class with values 10 and 10`? I've updated my class to take self arguments, thanks for that notice! – Jonas Palačionis Jun 12 '20 at 08:17