all Python 3OOPterm
Instance and class attributes
attributes
Class attributes are shared by every instance. Instance attributes belong to one instance each. Mutable class attributes are a trap!
Syntax
class C:
class_attr = 0 # классовый
def __init__(self):
self.inst_attr = 1 # экземплярный
Reading an attribute checks the instance first, then the class, but self.attr = ... always creates an instance attribute that shadows the class one. The real trap isn't reassignment — it's mutating a shared mutable class attribute (say, appending to a class-level list), which changes it for every instance at once.
Examples
class Dog:
species = 'Canis lupus' # классовый
def __init__(self, name):
self.name = name # экземплярный
d1 = Dog('Rex')
d2 = Dog('Max')
print(d1.species, d2.species) # → Canis lupus Canis lupus
print(d1.name, d2.name) # → Rex Max
# Изменение классового атрибута через класс
Dog.species = 'Canis familiaris'
print(d1.species) # → Canis familiaris
# Затенение классового атрибута
d1.species = 'Wolf' # только у d1
print(d1.species) # → Wolf
print(d2.species) # → Canis familiaris
# Изменяемый классовый атрибут — ловушка!
class BadList:
items = [] # общий для всех!
b1 = BadList(); b2 = BadList()
b1.items.append(1)
print(b2.items) # → [1] (список общий на всех — ловушка)
class GoodList:
def __init__(self):
self.items = [] # каждому свой
g1 = GoodList(); g2 = GoodList()
g1.items.append(1)
print(g2.items) # → []
class Counter2:
count = 0
def __init__(self):
Counter2.count += 1
self.id = Counter2.count
Counter2(); c3 = Counter2()
print(c3.id, Counter2.count) # → 2 2
# vars() vs dir()
class A:
x = 1
def __init__(self):
self.y = 2
a = A()
print(vars(a)) # → {'y': 2} (только экземплярные)
See also
Open in the full glossarydocs.python.orgReport an inaccuracy