You have already learned how to store data inside
__init__ using self. These are instance attributes. Each object gets its own unique copy, which is perfect for things like a name or an age that differ from one object to the next.But what if you have data that should be exactly the same for every single instance of your class? For example, all dogs are
Canis familiaris. You do not want each dog to carry its own copy of this fact. Instead, you can store it directly on the class itself.class Dog:
species = 'Canis familiaris' # Class attribute
def __init__(self, name):
self.name = name # Instance attributespecies is a class attribute. It lives on the class object itself. When you create two different dogs, they both point to this single shared value.class Dog:
species = 'Canis familiaris'
def __init__(self, name):
self.name = name
rex = Dog('Rex')
bella = Dog('Bella')
print(rex.species) # Canis familiaris
print(bella.species) # Canis familiarisYou might wonder why you would use a class attribute instead of just putting it in
__init__. The main reason is clarity and memory. It tells other programmers, "This value defines the type, not the individual." If every instance needs to know its team name or default settings, a class attribute keeps your code clean.Now, consider a common problem: counting how many objects have been created. You could try using an instance attribute to store the count, but each new object would start with its own counter at zero or one. That does not give you the total number of all instances.
A class attribute is perfect for this because it acts as a global ledger shared by everyone. When
__init__ runs, you can increase that single shared counter.class Counter:
total = 0 # Class attribute
def __init__(self):
self.id = 'new'
type(self).total += 1type(self) is a safe way to access the class itself from within an instance. By adding one to total, every new object updates the same shared number.