Since Python is a dynamic language, instances created from a class can be bound to arbitrary attributes.
Attributes can be bound to an instance via instance variables or the self variable:
class Student(object):
def __init__(self, name):
self.name = name
s = Student('Bob')
s.score = 90
But what if we need to bind an attribute to the Student class itself? We can define the attribute directly inside the class—this is a class attribute, which belongs to the Student class:
class Student(object):
name = 'Student'
Once a class attribute is defined, although it belongs to the class, all instances of the class can access it. Let’s test this:
>>> class Student(object):
... name = 'Student'
...
>>> s = Student() # Create instance s
>>> print(s.name) # Print the name attribute (instance has no name attribute, so it looks up the class's name attribute)
Student
>>> print(Student.name) # Print the class's name attribute
Student
>>> s.name = 'Michael' # Bind the name attribute to the instance
>>> print(s.name) # Instance attributes take precedence over class attributes, so it masks the class's name attribute
Michael
>>> print(Student.name) # The class attribute still exists and can be accessed via Student.name
Student
>>> del s.name # Delete the instance's name attribute
>>> print(s.name) # Access s.name again—since the instance's name attribute is gone, the class's name attribute is displayed
Student
From the example above, we can see that you should never use the same name for instance attributes and class attributes when writing code. An instance attribute with the same name will mask the class attribute, but if you delete the instance attribute, accessing the name will return the class attribute instead.
To count the number of students, add a class attribute to the Student class that automatically increments each time an instance is created:
class Student(object):
count = 0
def __init__(self, name):
self.name = name
# Test:
if Student.count != 0:
print('Test failed!')
else:
bart = Student('Bart')
if Student.count != 1:
print('Test failed!')
else:
lisa = Student('Bart')
if Student.count != 2:
print('Test failed!')
else:
print('Students:', Student.count)
print('Test passed!')