1

I'm trying to simplify my code to increase productivity and avoid typing errors and Object Oriented Programming (OOP) seems the way to follow. I'm new to OOP and have started to learn about classes and methods in Python. I'm working in a personal project involving consecutive steps to get a final result in which every step depends on the results of previous steps but intermediate results are also useful on its own.

Let's start with the definition of the class:

class MyClass():

def __init__(self, data):
    self.var_1 = data[0]
    self.var_2 = data[1]
    self.var_3 = data[2]
    
def method_1(self):
    self.result_1 = self.var_1 + self.var_2
    return self.result_1

def method_2(self):
    self.result_2 = self.var_3 * self.result_1
    return self.result_2

Next I create the object:

food = [7, 15, 32]
A = MyClass(food)
print(A.method_2)

The result:

<bound method MyClass.method_2 of <__main__.MyClass object at 0x00000249A2C54C48>> instead of the desired 704

I have done my homework and tried several solutions:

  1. First: call every method needed to get result prior to call the desired.

    B = MyClass(food) B.method_1() print(B.method_2())

Result:704

  1. Second: put the calls in init to force to evaluate them every time I instantiate the object. Discovered here:Enforce a sequence for calling methods in a class

    class MyClass():

     def __init__(self, data):
         self.var_1 = data[0]
         self.var_2 = data[1]
         self.var_3 = data[2]
    
         MyClass.method_1(self)
         MyClass.method_2(self)
    
    
     def method_1(self):
         self.result_1 = self.var_1 + self.var_2
         return self.result_1
    
     def method_2(self):
         self.result_2 = self.var_3 * self.result_1
         return self.result_2
    

Creating and calling gives 704:

C= MyClass(food)
print(C.method_2())

This can be modified using a idea from this thread:Run all functions in class

Defining a new method within the class:

def method_all(self):
        MyClass.method_1(self)
        MyClass.method_2(self)

Calling before does the trick

E = MyClass(food)
E.method_all()
print(E.method_2())

Is there a preferred method? Another solution that forces to evaluate needed methods before the desired one?

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
S. Cava
  • 13
  • 3
  • Is there any reason why you cannot invoke `method_1` from `method_2` like `self.result_2 = self.var_3 * self.method_1()` – Sam Daniel Jun 28 '20 at 11:17
  • Very descriptive question, can you fix the code formatting - especially indentation - of the code snippets. – jadelord Jun 28 '20 at 12:35
  • @SamDaniel. I think you are pointing in the same way as BossaNova suggestion. It worked. – S. Cava Jun 30 '20 at 16:02

2 Answers2

0

Here is one way using hasattr:

def method_2(self):
    if not hasattr(self, 'result_1'):
        self.method_1()
    self.result_2 = self.var_3 * self.result_1
Håkon Hægland
  • 39,012
  • 21
  • 81
  • 174
0

Regarding your class itself and the way you first tried to print the results: you called a method the way an attribute is called, that is, without parenthesis (in your print statement). Second, you should call method_1 to define result_1 before using it (even if it has "self", it's not automatically defined). By the way, you do not need to repeat "self" when you return the variable at the end of the method.

So trying to stay as close to your original code (the simplest), this is a working solution:

class MyClass():
    def __init__(self, data):
        self.var_1 = data[0]
        self.var_2 = data[1]
        self.var_3 = data[2]

    def method_1(self):
        result_1 = self.var_1 + self.var_2
        return result_1

    def method_2(self):
        result_1 = self.method_1()
        result_2 = self.var_3 * result_1
        return result_2


food = [7, 15, 32]
A = MyClass(food)
print(A.method_2())
BossaNova
  • 1,509
  • 1
  • 13
  • 17