It is certainly possible to accomplish everything that we would ever
want to do with our Person
class from the previous section by writing top-level
functions, and this is the approach we’ve taken with data classes up to
this point. An alternate and commonly-used approach is to define
methods for a data type, which become part of the interface of
that data type. Remember that methods are just functions that belong to
a data type—but this “belonging to” is not just a conceptual
relationship! Defining and using methods have concrete requirements and
consequences in Python, and software engineering in general. When we
define a data class and top-level functions, the interface of a data
class itself only consists of its attributes; we have to remember to
import those functions separately in order to use them. When we define a
class with methods, those methods are always bundled with the
class, and so any instance of the class can use those methods, without
needing to import them separately.
We have seen one example of a method definition already: the
initializer, __init__
. More generally, any function that
operates on an instance of a class can be converted into a method by
doing the following:
self
.For example, suppose we had the following function to increase a person’s age:
def increase_age(person: Person, years: int) -> None:
"""Add the given number of years to the given person's age.
>>> david = Person('David', 'Liu', 100, '40 St. George Street')
>>> increase_age(david, 10)
>>> david.age
110
"""
= person.age + years person.age
We can turn increase_age
into a Person
method as follows:
class Person:
"""A custom data type that represents data for a person."""
str
given_name: str
family_name: int
age: str
address:
def __init__(self, given_name: str, family_name: str, age: int, address: str) -> None:
"""Initialize a new Person object."""
self.given_name = given_name
self.family_name = family_name
self.age = age
self.address = address
def increase_age(self, years: int) -> None:
"""Add the given number of years to this person's age.
>>> david = Person('David', 'Liu', 100, '40 St. George Street')
>>> david.increase_age(10)
>>> david.age
110
"""
self.age = self.age + years
Notice that we now use parameter self
(without a type
annotation) to access instance attributes, just as we did in the
initializer. In our function docstring, the phrase “the given person”
changes to “this
person”, We typically use the word “this” in a method docstring
to refer to the object instance that self
refers to. In
fact, some other programming languages also use this
instead of self
as a variable or keyword to refer to this
object in code. and our doctest example changes the call to
increase_age
to Person.increase_age
.
In general, Python uses the following syntax for defining a method:
class <ClassName>:
"""..."""
<instance attributes/types omitted>
def <method_name>(self, <param>: <type>, ...) -> <return type>:
"""Method docstring"""
<statement>
...