Should all member variables be initialized in __init__ Should all member variables be initialized in __init__ python python

Should all member variables be initialized in __init__


In object-oriented programming it's up to the developer to ensure an object is always in a consistent state after instantiation and after a method finishes. Other than that you're free to develop the class as you wish (keeping in mind certain principles with subclassing / overriding and so on).

A tool such as Pylint will warn when you're setting instance variables outside __init__. It can be argued that setting all instance variables in the __init__ is cleaner but it's not a rule that must be abided by at all times.


I would actually discourage initializing variables you don't always need in __init__ to an arbitrary default value.

I do question your use of OO if this is the case, but I'm sure there is a valid and understandable case where __init__ will not do everything, and the class will want to further modify itself by adding additional attributes with other methods.

The proper way in my opinion to test if a variable was set while running a method that may want to use it would be to use hasattr. This is in the case that this is a valid way to use the method and the test just switches behavior in a sensible way.

Another way would be to try and use it and handle the exception and provide some user friendly information about what the user of your class is doing wrong. This is in the case the method needs the attribute to be set before running.

i.e. Hey man, you did initialize the class, but you need to make sure the z attribute exists by calling the z_init method before running the z_run method.

Another, arguably the more pythonic way, would be to just document how to use the method in the docstring and then let the exception fly when it is used improperly. This is good enough for the first implementation of something and you can then focus on the next task. This is in the same situation as above, the method needs the attribute to be set.

The reason I do not like the idea of initializing variables to arbitrary defaults is this can be confusing (because it is arbitrary) and is line noise.

If the value is not arbitrary and simply a default value that can be changed you should be using a default value in the __init__ method that can be overridden. It can also actually be a valid initial state, which is also not arbitrary and you should set it in the __init__ method.

So the real answer is it depends, and you should probably avoid it and question your use of OO if you are doing this either by adding attributes in other methods or initializing attributes to arbitrary values.

While Simeon Visser is saying to keep your object in a consistent state, he has no basis for what consistency is based on your abstract example. While Pylint warns on this kind of thing, warnings from lint programs are simply so a high level reviewer can be alerted of things that usually indicate code smell. I say high level reviewer because a real reviewer should be reading and understanding all of your code, and thus not really need Pylint.

An example that breaks the rule of thumb:

class Mutant(object):    """A mutant!"""    def __init__(self):        """A mutant is born with only 1 eye and 1 mouth"""        self.eyes = 1        self.mouth = 1        self.location = 'Montana'    def roll_to(self, location):        """If they have limbs, running is less dangerous"""        if hasattr(self, 'limbs'):             print 'Your mutant broke its limbs off!!'             del self.limbs        self.location = location    def run_to(self, location):        """If they don't have limbs, running is not effective"""        if not hasattr(self, 'limbs'):             print 'Your mutant tries to run but he has no limbs.'        else:             self.location = location    def grow_limbs(self, number_of_limbs):         """Ah, evolution!"""         assert number_of_limbs > 0, 'Cannot grow 0 or less limbs...'         if hasattr(self, 'limbs'):             self.limbs += number_of_limbs         else:             self.limbs = number_of_limbs


Here is an excerpt from sololearn.com (a free site to learn python)

"Properties provide a way of customizing access to instance attributes. They are created by putting the property decorator above a method, which means when the instance attribute with the same name as the method is accessed, the method will be called instead.

One common use of a property is to make an attribute read-only."

Example (also from sololearn.com):

class Pizza:    def __init__(self, toppings):    self.toppings = toppings    @property    def pineapple_allowed(self):       return False   pizza = Pizza(["cheese", "tomato"])   print(pizza.pineapple_allowed)   pizza.pineapple_allowed = True

Result:

  >>> False AttributeError: can't set attribute >>>

If var3 depends on var1 and var2 you could do

class myClass:    def __init__(self,var1,var2):        self.var1=var1        self.var2=var2    @property    def var3(self):        return(self.var1+self.var2)  #var3 depends on var1 and var2 m1=myClass(1,2) print(m1.var3)   # var3 is 3

var3 can also be set to whatever you want using a setter function. Note that you can avoid setting var3 to an arbitrary value by using None.

class myClass2(object):    def __init__(self,var1,var2):        self.var1=var1        self.var2=var2        self._var3=None     # None or an initial value that makes sense        @property        def var3(self):            return(self._var3)        @var3.setter        def var3(self,value):            self._var3=value   m2=myClass(1,2)   print(m2.var3)        # var3 is none   print(m2.var3(10))    # var3 is set to 10