6

Is there any difference in functionality and what happens behind the scenes between

class Class:
    def __init__(self, var1):
        self.var1 = var1

and

class Class:
    var1 = ""
    def __init__(self, var1):
        self.var1 = var1

in Python?

Rohan
  • 482
  • 6
  • 16
  • 2
    I think the second option declares a Class.var1 variable that is share dbetween all instances. – DainDwarf Dec 29 '15 at 07:44
  • @martineau: I don't think this is a duplicate, but would like to discuss it. The other question seems to be about how to choose between the two in a specific context, whereas this question is about *what the difference in semantics* is. The other question does seem to have a high quality answer about the semantics, that would be better applied to this question than that one. – Karl Knechtel Jun 04 '22 at 12:03

2 Answers2

12

Let's explore a bit. This is your class:

class Class:
    var1 = 'in class'
    def __init__(self, var1):
        self.var1 = var1

c = Class('in inst')

Accessing c.var1 shows the var1 from the instance:

>>> c.var1
'in inst'

It is located inside __dict__ of c:

>>> c.__dict__
{'var1': 'in inst'}

The class variable var1 is in __dict__ of Class:

>>> Class.__dict__['var1']
'in class'

Now make a class with only a class variable:

class Class2:
    var1 = 'in class'

c2 = Class2()

Since there is nothing in the instance, var1 from the class will be used:

>>> c2.var1
'in class'

The __dict__ of c2 is empty:

>>> c2.__dict__
{}

Python always looks for var1 first in the instance and than falls back to the class.

Mike Müller
  • 82,630
  • 20
  • 166
  • 161
5

As I pointed out in comment, the Class.var1 is a shared variable. It could be accessed for each instance as self.var1 if you don't erase it with a non-shared variable in __init__. Here is a sample of what happens :

class Test(object):
    shared = 0
    def __init__(self, i):
        self.notshared = i
    def intro(self):
        print("Shared is " + str(self.shared))
        print("NotShared is " + str(self.notshared))

test1 = Test(4)

test1.intro()
# Shared is 0
# NotShared is 4

Test.shared = 5
test1.intro()
# Shared is 5
# NotShared is 4

test2 = Test(3)
test2.intro()
# Shared is 5
# NotShared is 3

Be aware however that if you write the self.shared variable afterwards, you do not access the shared variable with self.shared anymore:

test1.shared = 12
test1.intro()
# Shared is 12
# NotShared is 4
test2.intro()
# Shared is 5
# NotShared is 3
DainDwarf
  • 1,651
  • 10
  • 19