#class with class-level attributes
class Data:

    s = 100 #class-level attribute, shared across all instances

    def __init__(self, x):    
        self.a = x              #instance-level attribute

    def printData(self):        #just another method
        print(f"s = {self.s}, a = {self.a}")    #can access instance/class attribute anywhere in class

print(f"Data.s = {Data.s}") #can be accessed directly - Data.s = 100

o1 = Data(10)
o2 = Data(20)

o1.printData() #s = 100, a = 10
o2.printData() #s = 100, a = 20

#can access class/instance attributes outside class using instance variable
print(f"o1.s = {o1.s}, a = {o1.a}") #o1.s = 100, a = 10
print(f"o2.s = {o2.s}, a = {o2.a}") #o2.s = 100, a = 20

Data.s = 200 #affects in every instance
o1.printData() #s = 200, a = 10
o2.printData() #s = 200, a = 20
print(f"Data.s = {Data.s}") #Data.s = 200

#BEWARE
o1.s = 1000 #creates new instance attribute inside 'o1' (does not modify Data.s)
o1.printData() #s = 1000, a = 10
print(f"Data.s = {Data.s}") #Data.s = 200
1a15af52d5c94b387b7a9e58d05ff37f9677ce92
class Data:
    <mask token>

    def __init__(self, x):
        self.a = x

    def printData(self):
        print(f's = {self.s}, a = {self.a}')


<mask token>

class Data:
    s = 100

    def __init__(self, x):
        self.a = x

    def printData(self):
        print(f's = {self.s}, a = {self.a}')


<mask token>

class Data:
    s = 100

    def __init__(self, x):
        self.a = x

    def printData(self):
        print(f's = {self.s}, a = {self.a}')


print(f'Data.s = {Data.s}')
<mask token>
o1.printData()
o2.printData()
print(f'o1.s = {o1.s}, a = {o1.a}')
print(f'o2.s = {o2.s}, a = {o2.a}')
<mask token>
o1.printData()
o2.printData()
print(f'Data.s = {Data.s}')
<mask token>
o1.printData()
print(f'Data.s = {Data.s}')

class Data:
    s = 100

    def __init__(self, x):
        self.a = x

    def printData(self):
        print(f's = {self.s}, a = {self.a}')


print(f'Data.s = {Data.s}')
o1 = Data(10)
o2 = Data(20)
o1.printData()
o2.printData()
print(f'o1.s = {o1.s}, a = {o1.a}')
print(f'o2.s = {o2.s}, a = {o2.a}')
Data.s = 200
o1.printData()
o2.printData()
print(f'Data.s = {Data.s}')
o1.s = 1000
o1.printData()
print(f'Data.s = {Data.s}')

#class with class-level attributes
class Data:

    s = 100 #class-level attribute, shared across all instances

    def __init__(self, x):    
        self.a = x              #instance-level attribute

    def printData(self):        #just another method
        print(f"s = {self.s}, a = {self.a}")    #can access instance/class attribute anywhere in class

print(f"Data.s = {Data.s}") #can be accessed directly - Data.s = 100

o1 = Data(10)
o2 = Data(20)

o1.printData() #s = 100, a = 10
o2.printData() #s = 100, a = 20

#can access class/instance attributes outside class using instance variable
print(f"o1.s = {o1.s}, a = {o1.a}") #o1.s = 100, a = 10
print(f"o2.s = {o2.s}, a = {o2.a}") #o2.s = 100, a = 20

Data.s = 200 #affects in every instance
o1.printData() #s = 200, a = 10
o2.printData() #s = 200, a = 20
print(f"Data.s = {Data.s}") #Data.s = 200

#BEWARE
o1.s = 1000 #creates new instance attribute inside 'o1' (does not modify Data.s)
o1.printData() #s = 1000, a = 10
print(f"Data.s = {Data.s}") #Data.s = 200