24

I'm building an object that has an attribute whose value is randomly generated at instantiation. The attribute will be assigned a new value (also randomly) from time to time, so I'm defining a method to do so. Is it bad form to initialize the attribute by calling that method from within __init__? It would be easy enough to avoid—I'd just have to duplicate a small amount of code—but it seems more elegant to call the method. Here's an example:

import random

class Robot(object):
    def __init__(self):
        self.setDirection()

    def setDirection(self):
        self.direction = random.random() * 360
ivan
  • 6,032
  • 9
  • 42
  • 65
  • 4
    No, it is not bad form to do so. The method (setDirection) is a function to help the class, if it needs to help the class fulfill its purpose during init or any other stage. – Inbar Rose Feb 11 '13 at 15:29
  • possible duplicate: http://stackoverflow.com/questions/3091833/calling-member-functions-from-a-constructor – Inbar Rose Feb 11 '13 at 15:30
  • There's a chance of getting bugs due to things being initialised in a different order than you expect, but as long as the helper method doesn't depend on any state of the object you should be fine. – millimoose Feb 11 '13 at 15:32
  • (An example of the above would be if you call a method overriden in the subclass from the `__init__` method of the superclass. Since the superclass constructor is usually called first, if the override assumes that the code in the subclass constructor has run you have a problem that's somewhat fiddly to resolve. Albeit less so in Python than in Java/C# because you can call `super().__init__()` whenever.) – millimoose Feb 11 '13 at 15:35
  • @ millimoose That's a good point, and I was unsure about doing this because I'm used to seeing attributes defined/initialized directly in `__init__`. – ivan Feb 11 '13 at 15:43

2 Answers2

20

It's fine to call instance methods within __init__, but be careful if they might be overridden in subclasses:

class A(object):

    def __init__(self):
        self.greet()

    def greet(self):
        print('Hello from A')


class B(A):

    def __init__(self, name):
        super(B, self).__init__()
        self.name = name

    def greet(self):
        print('Hello from B', self.name)

Now if B is instantiated, B.greet is called by A.__init__ before its preconditions are satisfied (self.name is not defined).

Aya Maguire
  • 131
  • 7
ecatmur
  • 152,476
  • 27
  • 293
  • 366
3

There's nothing wrong with calling other instance methods within __init__.


Note that in python there is a distinction between instance methods and class methods. I can't think of a good reason to use a class method within __init__ -- which isn't to say that a good reason doesn't exist, but that the cases are probably pretty rare.

mgilson
  • 300,191
  • 65
  • 633
  • 696