Classes in Python are defined using the class
keyword. The indented lines that follow the keyword are part of the class definition.
class Horse: # lines here are part of the definition of class Horse.
Initializers, Methods, and Instance Variables
In Python, the class definition typically contains function definitions (“methods” in object-oriented parlance) that define the “behavior” of instances of the class. A special function, named __init__(...)
, is used to initialize new instances of the class when they are created.
class Horse: def __init__(self, color="sorrel"): self.color = color
The first parameter to all methods in a class is a reference to the instance (object) of the class being manipulated. By Python convention, this parameter is named self
, but it doesn’t really matter to the Python compiler. In other object-oriented languages, like Java and C++, this parameter is implicit (not specified explicitly) and instead the reserved word this
is used to reference the current object.
Using this very short class definition, it is possible to create multiple horses with different colors.
silver = Horse("white") trigger = Horse("palomino") wilbur = Horse("palomino") buck = Horse("buckskin") secretariat = Horse()
If the color is not specified in the contructor (e.g., the secretariat
example), the default color (“sorrel”) is used.
The statement
self.color = color
assigns to the instance of the variable color
associated with the current object (self
), the value of the specified parameter named color
. Note that instance variable names and parameter names can be the same; using the dot notation is needed to disambiguate them.
The statement
print(trigger.color)
prints “palomino” to the console.
Instance variables are not declared in Python (unlike Java and C++). They are created automatically by references to self
. These references can be in the initializer method (__init__), in some other method, or just in code that references an instance of that class.
Consider this expanded Horse
example.
class Horse: def __init__(self, color="sorrel"): self.color = color def setBreed(self, breed): self.breed = breed; silver = Horse("white") trigger = Horse("palomino") wilbur = Horse("palomino") buck = Horse("buckskin") print(trigger.color) trigger.setBreed("grade") print(trigger.breed) trigger.gender = "stallion" print(trigger.gender)
The color
instance variable is set in the initializer method, so that all instances of the Horse
class have a color, even if Horse()
is called with no arguments (defaulting to “sorrel”).
The breed
instance variable is created and set by the setBreed
method.
The gender
instance variable is created and set by this code inline.
Note that instance variables are created dynamically when assigned a value. If no value is assigned, no instance variable is created. So, for example, the code sequence:
flicka = Horse() print(flicka.color) print(flicka.breed)
Prints “sorrel”, but then crashes with the error “AttributeError: Horse instance has no attribute ‘breed'”. Since the setBreed(...)
method was not called on the object referenced by flicka
, nor was the breed
variable explicitly set, the instance variable did not exist. Note that the error message says the Horse instance has no attribute ‘breed’. This phrasing is precise, since it says that the attribute is missing in this particular instance (object).
A typical convention is to assign values to all instance variables in the initializer, which forms a kind of documentation–identifying which variables the class is expecting to see in each instance. For example, the Horse
initializer could be rewritten as
def __init__(self, color="sorrel"): self.color = color self.breed = "unknown" self.gender = None
indicating that (1) the color can be specified as an initializer parameter, but defaults to “sorrel”, (2) the breed is “unknown”, and (3) the gender is not set to any value (None
). Even though the gender is not set, it does exist as a variable in the class instances, so accessing it no longer gives an error, returning None
instead.
Instance Variables and Class Variables
Variables declared at the “top level” in a class are attributes of the class–the same variable is common to all instances. Class variables are most commonly referenced using dot notation with the class name, e.g., Horse.herd_size
(see below). The variable can also be referenced through an instance, however, assigning this variable a value in this way creates a new copy of that variable local to the instance. This feature in Python can be confusing, especially for students familiar with Java or C++.
For example, we can modify the Horse
class to keep track of the herd size by introducing a class variable, herd_size
:
class Horse: herd_size = 0 def __init__(self, color="sorrel"): Horse.herd_size += 1 self.color = color self.breed = "unknown" self.gender = None
After creating several instances of Horse
, we can access the herd_size
variable to see how many there are:
silver = Horse("white") trigger = Horse("palomino") wilbur = Horse("palomino") buck = Horse("buckskin") secretariate = Horse() print(Horse.herd_size)
prints 5.
We can access the class variable through an instance, for example:
print(silver.herd_size)
also prints 5. However, if we attempt to modify the variable through an instance, a new (local) copy of the variable is created instead:
silver.herd_size = 0; print(silver.herd_size) print(Horse.herd_size) sea_biscuit = Horse() print(trigger.herd_size)
prints 0, 5, 6. The object referenced by silver now has a local copy of the herd_size
variable, but the Horse
class variable is unaffected, as are instances of Horse
that have not created their own local copies.
Private Variables and Methods
The Python language does not directly support private variables and methods in the Java/C++ sense–that is, variables that are not accessible by “clients” of the class. However, there is a common convention used in Python: variables and methods that begin with a underscore (“_”) are considered private and are not to be referenced outside the class.