Example of a case where declaring variable inside __init__ is bad

Context:

I was reading this article https://docs.python.org/3/tutorial/classes.html#a-first-look-at-classes section 9.3.5 example 2, where is showed that we can make a logical mistake by (in a class) declaring variable outside init. This got me thinking, what if I always declare my variable inside init just to be on a safer side and hence wanted to know any logical side effect. I suppose some coders won’t find my suggestion aesthetically pleasing but here I am primarily concerned about logic of the code.

I’m not sure what you are asking.

In python

class foo:
    # variables declared here are shared across all instances of the class
    shared_variable = "bar"

    def __init__ (self, private_value):
        # variables declared here are part of the specific instance of the class
        self._not_shared_variable = private_value

There is no question of ‘aesthetically pleasing’. You declare the variable outside of a method if it is common to all instances of the class. You declare the variable inside of methods if it is specific to a single instance of the class.

My observations are different from what you are saying.

Context: I was trying to code the structure of a linked list and I came up with the following two code.

class linked_list:
    i = 0
    c = []
    def __init__(self, a,b):
        
        self.a = a
        self.b = b

    def travel_the_list(self):
        while True:
            j = self.b[self.i]
            if j == 0:
                break
            self.c.append(self.a[j])
            self.i = j


        return self.c


x = linked_list([None, 'Item 1', 'Item 4', 'Item 2', 'Item 3'],[1,3,0,4,2])

print(x.travel_the_list())

gives me the same result as

class linked_list:
    
   
    def __init__(self, a,b):
        self.i = 0
        self.c = []
        self.a = a
        self.b = b

    def travel_the_list(self):
        while True:
            j = self.b[self.i]
            if j == 0:
                break
            self.c.append(self.a[j])
            self.i = j


        return self.c


x = linked_list([None, 'Item 1', 'Item 4', 'Item 2', 'Item 3'],[1,3,0,4,2])

print(x.travel_the_list())

now I don’t know which style to choose from. Then I read some documentation (link given above) where it showed that accident do happens if we carelessly put the variable outside __init__(). So my current theory is to always play safe and put every variable inside __init__(). I just wannted to confirm my theory with expirenced dev here.

Directly from the documentation you linked:

class Dog:

    kind = 'canine'         # class variable shared by all instances

    def __init__(self, name):
        self.name = name    # instance variable unique to each instance

You aren’t seeing this issue because you only have one instance of your class, but the documentation is still accurate. You should only put variable declarations in the class definition outside of methods when you want to share the data across all instances.

1 Like

Actually realized the error in my thinking after re-reading the document carefully again. For the benefit of future reader, I reiterate: what I considered problem (Example 2 of the link I mentioned) can also be treated as feature, (say give all possible tricks that can be performed by atleast one dog), in which case my argument fails.

In my context, as soon as I created one more object of the class for 1st code, I ran into problem and hence code 2 is more accurate wrt given task.

1 Like