Python - why use "self" in a class?

PythonOop

Python Problem Overview


How do these 2 classes differ?

class A():
    x=3

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

Is there any significant difference?

Python Solutions


Solution 1 - Python

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:

#!/usr/bin/env python
    
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's x:", x.x)

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

Output

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

Solution 2 - Python

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

Solution 3 - Python

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 is', Foo.i
...             print 'self.i is', self.i
...
>>> f = Foo() # Create an instance of the Foo class
>>> f.bar()
Foo.i is 3
self.i is 3
>>> Foo.i = 5 # Change the global value of Foo.i over all instances
>>> f.bar()
Foo.i is 5
self.i is 5
>>> f.i = 3 # Override this instance's definition of i
>>> f.bar()
Foo.i is 5
self.i is 3

Solution 4 - Python

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 by

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

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

Solution 5 - Python

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'.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionryeguyView Question on Stackoverflow
Solution 1 - PythonDouglas LeederView Answer on Stackoverflow
Solution 2 - PythonAndréView Answer on Stackoverflow
Solution 3 - PythonTerrorBiteView Answer on Stackoverflow
Solution 4 - PythonTMOTTMView Answer on Stackoverflow
Solution 5 - Pythonyabee-dabeeView Answer on Stackoverflow