Instance variables in methods outside the constructor (Python) -- why and how?

3.) But instance variables can also be defined/initialized outside the constructor, e.g. in the other methods of the same class.

I'd recommend providing a default state in initialization, just so its clear what the class should expect. In statically typed languages, you'd have to do this, and it's good practice in python.

Let's convey this by replacing the variable roar with a more meaningful variable like has_roared.

In this case, your meow_bigger() method now has a reason to set has_roar. You'd initialize it to false in __init__, as the cat has not roared yet upon instantiation.

class Cat():
    def __init__(self):
        self.meow = "Meow!"
        self.has_roared = False

    def meow_bigger(self):
         print self.meow + "!!!"
         self.has_roared = True

Now do you see why it often makes sense to initialize attributes with default values?

All that being said, why does python not enforce that we HAVE to define our variables in the __init__ method? Well, being a dynamic language, we can now do things like this.

>>> cat1 = Cat()
>>> cat2 = Cat()
>>> cat1.name = "steve"
>>> cat2.name = "sarah"
>>> print cat1.name
... "steve"

The name attribute was not defined in the __init__ method, but we're able to add it anyway. This is a more realistic use case of setting variables that aren't defaulted in __init__.


To initialize instance variables within the constructor, is - as you already pointed out - only recommended in python.

First of all, defining all instance variables within the constructor is a good way to document a class. Everybody, seeing the code, knows what kind of internal state an instance has.

Secondly, order matters. if one defines an instance variable V in a function A and there is another function B also accessing V, it is important to call A before B. Otherwise B will fail since V was never defined. Maybe, A has to be invoked before B, but then it should be ensured by an internal state, which would be an instance variable.

There are many more examples. Generally it is just a good idea to define everything in the __init__ method, and set it to None if it can not / should not be initialized at initialization.

Of course, one could use hasattr method to derive some information of the state. But, also one could check if some instance variable V is for example None, which can imply the same then. So in my opinion, it is never a good idea to define an instance variable anywhere else as in the constructor.

Your examples state some basic properties of python. An object in Python is basically just a dictionary. Lets use a dictionary: One can add functions and values to that dictionary and construct some kind of OOP. Using the class statement just brings everything into a clean syntax and provides extra stuff like magic methods.

In other languages all information about instance variables and functions are present before the object was initialized. Python does that at runtime. You can also add new methods to any object outside the class definition: Adding a Method to an Existing Object Instance


Remember that class members in "pure" Python are just a dictionary. Members aren't added to an instance's dictionary until you run the function in which they are defined. Ideally this is the constructor, because that then guarantees that your members will all exist regardless of the order that your functions are called.

I believe your example above could be translated to:

class Cat():
    def __init__(self):
        self.__dict__['meow'] = "Meow!"
    def meow_bigger(self):
        self.__dict__['roar'] = "Roar!"

>>> c = Cat()        # c.__dict__ = { 'meow': "Meow!" }
>>> c.meow_bigger()  # c.__dict__ = { 'meow': "Meow!", 'roar': "Roar!" }

Why is it best practice to initialize the instance variable within the constructor?

Clarity.

Because it makes it easy to see at a glance all of the attributes of the class. If you initialize the variables in multiple methods, it becomes difficult to understand the complete data structure without reading every line of code.

Initializing within the __init__ also makes documentation easier. With your example, you can't write "an instance of Cat has a roar attribute". Instead, you have to add a paragraph explaining that an instance of Cat might have a "roar" attribute, but only after calling the "meow_louder" method.

Clarity is king. One of the smartest programmers I ever met once told me "show me your data structures, and I can tell you how your code works without seeing any of your code". While that's a tiny bit hyperbolic, there's definitely a ring of truth to it. One of the biggest hurdles to learning a code base is understanding the data that it manipulates.

What general/specific mess could arise if instance variables are regularly initialized in methods other than the constructor?

The most obvious one is that an object may not have an attribute available during all parts of the program, leading to having to add a lot of extra code to handle the case where the attribute is undefined.

In what scenarios would it be better to initialize instance variables in the other methods, rather than in the constructor?

I don't think there are any.

Note: you don't necessarily have to initialize an attribute with it's final value. In your case it's acceptable to initialize roar to None. The mere fact that it has been initialized to something shows that it's a piece of data that the class maintains. It's fine if the value changes later.