Hawklaz
Hawklaz

Reputation: 336

Correct way to use constructor arguments when creating attributes

Is there a correct way to use the constructor arguments when I am creating other attributes? For example: do I use shape=arg3.shape OR shape=self.arg3.shape when I am creating self.arg4?

import numpy as np

class MyClass:

    def __init__(self, arg1, arg2, arg3=None, arg4=None):
        self.arg1 = arg1
        self.arg2 = arg2
        if arg3 is None:
            self.arg3 = np.array([[10, 10], [10, 10]])
        else:
            self.arg3 = arg3
        if (arg3 is None) and (arg4 is None):
            self.arg4 = np.ones(shape=(2,2))
        elif arg4 is None:
            print('Look at this case')
            self.arg4 = np.ones(shape=self.arg3.shape)
            # OR
            self.arg4 = np.ones(shape=arg3.shape)
        else:
            self.arg4 = arg4

    def print_args(self):
        print(self.arg1)
        print(self.arg2)
        print(self.arg3)
        print(self.arg4)

if __name__ == '__main__':
    x = np.array([[25, 20], [20, 25]])
    my_obj = MyClass(arg1=3, arg2=4, arg3=x)
    my_obj.print_args()

I'm guessing both work the same based on the output, but I am looking for an answer explaining what the best practice would be if any and the OOP reasoning behind it.

Upvotes: 0

Views: 397

Answers (3)

Pasquale
Pasquale

Reputation: 439

The two instructions shape=arg3.shape and shape=self.arg3.shape are different and they don't necessarily bring to the same output, according to the specific input given in the constructor. Let me explain why:

  • whenever you access a variable inside a method, if you prepend the keyword self, you refer to the object variable defined as a global variable within the object scope;
  • if you don't prepend the keyword self, you refer to any variable inside the function scope (e.g. inside __init__), that does not necessarily match the global variable inside the object.

That said, coming back to your question, and assuming you want to compute self.arg4 using the object variable self.arg3, then the correct instruction is shape=self.arg3.shape.

Why should you prepend self?

Shortly, self dereferences the memory where the object is stored, which is located in the process heap: here the object variables live.

The function, on the contrary, lives in the stack (as the function variables): it doesn't know where the object is and therefore where its variables are located in the heap. That's why you must use self.

Upvotes: 1

Navaneeth Reddy
Navaneeth Reddy

Reputation: 339

You should do this

self.arg4 = np.ones(shape=self.arg3.shape)

This is purely to increase the readability of the code.

self.arg4 = np.ones(shape=arg3.shape)

You are free to do anything that you like but this is just my opinion.

Upvotes: 0

Surya Prakash Reddy
Surya Prakash Reddy

Reputation: 89

Both shape=arg3.shape and shape=self.arg3.shape are not same.

In the first one, you using arg3.shape which points to the parameter from constructor. In the second one, you are using self.arg3.shape which points to the instance variable of the class. So, All instance variables should be accessed using self. You should not use self for variables in parameters.

Upvotes: 0

Related Questions