[Tutor] When to use def __init__ when making a class?

Steven D'Aprano steve at pearwood.info
Wed Aug 3 03:25:33 CEST 2011


brandon w wrote:
> I have two questions:
> 
> 1)  When should I use "def __init__(self):" when I create a class?

Whenever you need something to happen when you create an instance.


> 2)  Would these two classes have the same effect?

Technically, no, but in practice, you would find it hard to see the 
difference for the example given. But for slightly different examples, 
the difference would be astonishing.



> class Name:
>         def __init__(self):
>                 man = Marcus
>                 woman = Jasmine
>                 return self.man, self.woman

Did you try the code before posting it?

Three problems with it:

(1) Firstly, Marcus and Jasmine are not built-in Python commands, so 
trying to execute man = Marcus raises NameError. You need to use 
quotation marks to turn it into a string.

(2) Fixing that problem, man = "Marcus" doesn't do what you expect 
either, because it creates a local variable man and not an attribute.

(3) Last but not least, the return result of __init__ is ignored, so 
even though you try to return self.man and self.women, nothing happens.

Also, calling the class "Name" is a bad idea, because it doesn't have 
anything to do with what the class actually holds, which is a *pair* of 
names, one male and one female.


This code should be written as:


class Couple:
     def __init__(self):
         self.man = "Marcus"
         self.woman = "Jasmine"


This creates a class where every instance has its own independent 
attributes man and woman.


> class Name:
>         man = Marcus
>         woman = Jasmine
>         return man, woman


Again, did you try this? If you did, you would discover it raises 
SyntaxError: you can't include a return statement inside a class, 
because it is meaningless.

SyntaxError: 'return' outside function

This should be written as

class Couple:
     man = "Marcus"
     woman = "Jasmine"


This creates a class where every instance shares the same pair of 
attributes.



In this example, the difference is not very great, because strings 
cannot be modified in place. If you try to store a new value for the 
attribute, Python defaults to creating an independent instance attribute 
rather than changing the shared class attribute.


Here is an example that may help show the difference:


class TestAttributes:
     a = [1, 2, 3]  # Shared, and mutable.
     def __init__(self):
         self.b = [1, 2, 3]  # Not shared.


Now, using this:


 >>> x = TestAttributes()  # Create a new instance.
 >>> y = TestAttributes()  # And another one.
 >>>
 >>> x.a
[1, 2, 3]
 >>> y.a
[1, 2, 3]
 >>> x.a.append(42)  # Modify the SHARED list.
 >>> y.a  # And all instances see the change!
[1, 2, 3, 42]
 >>>
 >>> x.b
[1, 2, 3]
 >>> x.b.append(999)  # Modify the non-shared list.
 >>> x.b
[1, 2, 3, 999]
 >>> y.b  # Other instances are unchanged.
[1, 2, 3]





-- 
Steven



More information about the Tutor mailing list