ryeguy
ryeguy

Reputation: 66851

What difference does it make to use "self" to define a member in a Python class?

How do these 2 classes differ?

class A():
    x = 3

class B():
    def __init__(self):
        self.x = 3

Is there any significant difference?

Upvotes: 88

Views: 59149

Answers (5)

TMOTTM
TMOTTM

Reputation: 3381

I used to explain it with this example

# By TMOTTM

class Machine:

    # Class Variable counts how many machines have been created.
    # The value is the same for all objects of this class.
    counter = 0

    def __init__(self):

        # Notice: no 'self'.
        Machine.counter += 1

        # Instance variable.
        # Different for every object of the class.
        self.id = Machine.counter

if __name__ == '__main__':
    machine1 = Machine()
    machine2 = Machine()
    machine3 = Machine()

    #The value is different for all objects.
    print('machine1.id', machine1.id)
    print('machine2.id', machine2.id)
    print('machine3.id', machine3.id)

    #The value is the same for all objects.
    print('machine1.counter', machine1.counter)
    print('machine2.counter', machine2.counter)
    print('machine3.counter', machine3.counter)

The output then will be

machine1.id 1
machine2.id 2
machine3.id 3

machine1.counter 3
machine2.counter 3
machine3.counter 3

Upvotes: 18

TerrorBite
TerrorBite

Reputation: 352

A.x is a class variable, and will be shared across all instances of A, unless specifically overridden within an instance. B.x is an instance variable, and each instance of B has its own version of it.

I hope the following Python example can clarify:

>>> class Foo():
...     i = 3
...     def bar(self):
...         print('Foo.i:', Foo.i)
...         print('self.i:', self.i)
... 
>>> f = Foo()  # Create an instance of the Foo class
>>> f.bar()
Foo.i: 3
self.i: 3
>>> Foo.i = 5  # Change the global value of Foo.i over all instances
>>> f.bar()
Foo.i: 5
self.i: 5
>>> f.i = 7  # Override this instance's definition of i
>>> f.bar()
Foo.i: 5
self.i: 7

Upvotes: 25

Douglas Leeder
Douglas Leeder

Reputation: 53310

A.x is a class variable. B's self.x is an instance variable.

i.e. A's x is shared between instances.

It would be easier to demonstrate the difference with something that can be modified like a list:

class A:
    x = []
    def add(self):
        self.x.append(1)

class B:
    def __init__(self):
        self.x = []
    def add(self):
        self.x.append(1)

x = A()
y = A()
x.add()
y.add()
print("A x:", x.x)

x = B()
y = B()
x.add()
y.add()
print("B x:", x.x)

Output

A x: [1, 1]
B x: [1]

Upvotes: 147

yabee-dabee
yabee-dabee

Reputation: 116

I've just started learning Python and this confused me as well for some time. Trying to figure out how it all works in general I came up with this very simple piece of code:

# Create a class with a variable inside and an instance of that class
class One:
    color = 'green'

obj2 = One()


# Here we create a global variable(outside a class suite).
color = 'blue'         

# Create a second class and a local variable inside this class.       
class Two:             
    color = "red"

    # Define 3 methods. The only difference between them is the "color" part.
    def out(self):     
        print(self.color + '!')

    def out2(self):
        print(color + '!')

    def out3(self):
        print(obj2.color + '!')

# Create an object of the class One
obj = Two()

When we call out() we get:

>>> obj.out()

red!

When we call out2():

>>> obj.out2()

blue!

When we call out3():

>>> obj.out3()

green!

So, in the first method self specifies that Python should use the variable(attribute), that "belongs" to the class object we created, not a global one(outside the class). So it uses color = "red". In the method Python implicitly substitutes self for the name of an object we created(obj). self.color means "I am getting color="red" from the obj"

In the second method there is no self to specify the object where the color should be taken from, so it gets the global one color = 'blue'.

In the third method instead of self we used obj2 - a name of another object to get color from. It gets color = 'green'.

Upvotes: 4

André
André

Reputation: 13317

Just as a side note: self is actually just a randomly chosen word, that everyone uses, but you could also use this, foo, or myself or anything else you want, it's just the first parameter of every non static method for a class. This means that the word self is not a language construct but just a name:

>>> class A:
...     def __init__(s):
...        s.bla = 2
... 
>>> 
>>> a = A()
>>> a.bla
2

Upvotes: 60

Related Questions