It depends. Defining all the attributes inside __init__
itself generally makes the code more readable, but if the class has a lot of attributes and you can easily divide them into logical groups then it makes sense to initialise each group of attributes in its own initialising method. You may wish to indicate that such methods are private by giving them a name that commences with a single underscore.
Note that if the class is derived from one or more other classes (apart from object
) then you will have to call super.__init__
to initialise the attributes inherited from the parent class(es).
The bottom line is that all instance attributes should exist by the time that __init__
finishes executing. If it's not possible to set a proper value for some attribute in __init__
then it should be set to an appropriate default value, eg an empty string, list, etc, None
, or a sentinel value like object()
.
Of course, the above doesn't apply to @property
attributes, but even those will generally have an underlying "private" attribute that should be set in __init__
.
For more info about properties, please see Raymond Hettinger's excellent Descriptor HowTo Guide in the Python docs.
As juanpa.arrivillaga mentions in the question comments, we don't actually declare variables in Python. That's basically because the Python data model doesn't really have variables like C and many other languages do. For a succinct explanation with nice diagrams please see Other languages have "variables", Python has "names". Also see Facts and myths about Python names and values, which was written by SO veteran Ned Batchelder.