2

What is the difference in the following two examples?

#Example 1
class Foo:
    
    var = None
    
    def __init__(self):
        self.var = 1
        
#Example 2
class Bar:

    var = None
    
    def __init__(self):
        Foo.var = 1

How does var vary between the two examples?

Is Example 1 a static variable or is it an incorrect use of a variable declaration as a static variable?

jason m
  • 6,519
  • 20
  • 69
  • 122
  • Example 1 defines both a class attribute and an instance attribute. Example 2 defines only a class attribute, which `Bar.__init__` updates every time it is called. – chepner Sep 01 '21 at 01:42

2 Answers2

2

Simply

  • Foo.var changes class state.
  • self.var changes object state.
class Foo():

  var = None
    
  def __init__(self):
    Foo.var = 1

class Bar():

  var = None

  def __init__(self):
    self.var = 1

print('Foo before', Foo.var)
print('Bar before', Bar.var)

foo = Foo()
bar = Bar()

print('foo', foo.var)
print('bar', bar.var)

print('Foo after', Foo.var)
print('Bar after', Bar.var)

Foo.var = 2
Bar.var = 2

print('foo after class changed', foo.var)
print('bar after class changed', bar.var)

output:

Foo before None
Bar before None
foo 1
bar 1
Foo after 1
Bar after None
foo after class changed 2
bar after class changed 1

About second question:

Is Example 1 a static variable or is it an incorrect use of a variable declaration as a static variable?

Both vars are static (or class) variables. You able to call them without creating instance. (Foo.var, Bar.var)

class Foo():

  class_variable = 'c'
    
  def __init__(self):
    self.instance_variable = 'i'

print('Class variable of class', Foo.class_variable)

try:
  print(Foo.instance_variable)
except Exception as e:
  print('This error happens when we call instance variable without creating instance')
  print(e)

instance = Foo()

print('Class variable of instance', instance.class_variable)
print('Instance variable of instance', instance.instance_variable)
Class variable of class c
This error happens when we call instance variable without creating instance
type object 'Foo' has no attribute 'instance_variable'
Class variable of instance c
Instance variable of instance i
rzlvmp
  • 7,512
  • 5
  • 16
  • 45
0

Changing examples from Foo and Bar to cars and trucks because I think a familiar object might be easier to grok:

#Example 1
class Car:
    
    age = None
    
    def __init__(self):
        self.age = 1

    def olden(self):
        self.age += 1
        
#Example 2
class Truck:

    age = None
    
    def __init__(self):
        Truck.age = 1
        
    def olden(self):
        Truck.age += 1

print("---Cars---")

accord = Car()
print(f"{accord.age=}")
accord.olden()
print(f"{accord.age=}")

camry = Car()
print(f"{camry.age=}")
print(f"{accord.age=}")

print("\n---Trucks---")
ram = Truck()
print(f"{ram.age=}")
ram.olden()
print(f"{ram.age=}")

f150 = Truck()
print(f"{f150.age=}")
print(f"{ram.age=}")

This prints

---Cars---
accord.age=1
accord.age=2
camry.age=1
accord.age=2

---Trucks---
ram.age=1
ram.age=2
f150.age=1
ram.age=1

What's happening is the cars' variables are being accessed with self, and since the Accord and Camry are separate car objects, they can age independently.

The trucks' variables are being access with Truck, so creating an F150 resets the age of the existing Ram.

user1717828
  • 7,122
  • 8
  • 34
  • 59