Introduction
Object-oriented programming (OOP), which is a programming paradigm that groups code and the data it uses together, is a key feature in Python. The topic of OOP concepts and techniques alone can be covered by a full course in its own right. Since this course is more focused on Python features, this lesson will only cover the basics of how OOP is done in Python, specifically focusing on Python classes and objects. The primary goal of this lesson is to educate you enough about Python’s OOP features to enable you to better understand the rest of this course.
Understanding the Basics
At the heart of OOP are objects and classes, which allow for the creation of modular and scalable programs.
What is an Object?
In programming, an object is a collection of data and methods that operate on that data.
Methods are functions, which are reusable blocks of code, that belong to an object and have easy access to its data.
For example, a Python list, which is an ordered collection of elements written like [1, 2, 3, 4, 5]
, is an object. The data of the list are the elements inside it, and it has various methods to manipulate these elements.
Example:
my_list = [1, 2, 3, 4, 5] my_list.append(6) print(my_list) my_list.remove(3) print(my_list)
Output:
[1, 2, 3, 4, 5, 6] [1, 2, 4, 5, 6]
In the example above:
my_list
is a list that’s initialized to[1, 2, 3, 4, 5]
(line 1).- The
append()
method is used to add the number 6 to the end of the list, resulting in[1, 2, 3, 4, 5, 6]
(line 3). - The
remove()
method is then used to remove the number 3 from the list, resulting in[1, 2, 4, 5, 6]
(line 6).
These methods demonstrate how objects in Python can encapsulate data and provide functionality to manipulate that data.
It is important to understand the basics of OOP when programming in Python because everything in Python is an object. It is one of the core principles of Python’s design.
What is a Class?
A class is a blueprint for creating objects. It defines a set of attributes (data) and methods that the objects will have.
For example, Python lists, such as [1, 2, 4, 5, 6]
, are instances of a class named list
.
Objects are also referred to as instances of a class.
Real-world Analogy
Understanding classes and objects can be easier with a real-world analogy. Think of a class as a blueprint for a house. The blueprint defines the structure and features of the house, such as the number of rooms, the type of windows, and the layout.
In this analogy,
- Class (Blueprint): A class is like a blueprint that defines the attributes (rooms, windows) and methods (functions, such as opening a window or locking a door) of a house.
- Object (House): An object is like a specific house built from the blueprint. Each house built from the same blueprint will have the same structure and features, but they can have different details and states, such as colors and whether a window is open or closed.
Creating Classes and Objects
Defining a Class
Now that you understand what classes and objects are, let’s look at how you can define your own a class in Python.
Here is the basic syntax of defining a class in Python:
class ClassName: ... # The code that defines the class.
class
: The keyword that starts the statement that defines a new class.ClassName
: The name of the class. By convention, you should name classes you create with CamelCase, i.e. a text style that has the first letter of each word capitalized and the rest lower case.
In Python,
...
is a special object of theellipsis
class that can be used as a placeholder for code that hasn’t been implemented yet. It is a singleton object, meaning it’s the only object of its class.
Example:
class Dog: pass
The example above creates a class named Dog
. For now, the body of the statement is pass
, which is Python’s way of having a code block that does nothing. (You will learn what you can do with this code block a little later.)
pass
is a Python keyword that means no-operation. It tells Python to do nothing. Like the ellipsis, it’s another way to have a placeholder for code that you are going to fill in later.
Creating an Object
Now that you’ve defined a class, you can create objects of that class. To do so, simply write the class name followed by parentheses ()
.
Here is the basic syntax for creating an object:
ClassName()
Example:
my_dog = Dog()
In the example above, my_dog
is a variable that’s assigned a newly created object of the Dog
class.
Class Components
Instance Attributes
Instance attributes are variables that hold data specific to an instance of a class, i.e. object. They are defined within a class, but their values are unique to each object created from the class.
To define instance attributes in a class, you use the __init__
() method. This is a special method that initializes an object’s attributes when the object is created. The __init__
() method is called automatically by Python when a new instance of the class is created.
Here is the basic syntax for defining instance attributes within the __init__
() method:
class ClassName: def __init__(self, attribute1, attribute2, ...): self.attribute1 = attribute1 self.attribute2 = attribute2 ...
def __init__(self, attribute1, attribute2, ...)
: Defines the__init__
() method. Theself
parameter refers to the instance being created and allows access to its attributes and methods.self.attribute1 = attribute1
: Creates an instance attribute namedattribute1
and assigns it the value passed to__init__
() in theattribute1
parameter. The attribute and parameter don’t need to have the same name, but it usually makes the code easier to understand.
Example:
class Dog: def __init__(self, name, age): self.name = name self.age = age
In the example above:
- The
Dog
class has an__init__
() method defined with parametersname
andage
(line 2). - The instance attributes
self.name
andself.age
are initialized with the values passed to the__init__
() method (line 3 and 4).
To pass values to the __init__
() method, place them in the parentheses, separated by commas, when you create an object. The self
parameter is handled by Python automatically, and you therefore don’t need to include it.
Example:
my_dog = Dog("Snoopy", 5) print(my_dog.name) print(my_dog.age)
Output:
Snoopy 5
In the example above:
my_dog
is an instance of theDog
class with thename
attribute set to “Snoopy” and theage
attribute set to 5 (line 1).- The
print
statements output the values of thename
andage
attributes ofmy_dog
(lines 2-3).
As you can see from the example, to access an object’s attribute, you follow the object by a period (.
) and the attribute name. This syntax is commonly referred to as “dot notation”.
Instance attributes let each object maintain its own state and data. As the next example shows, you can create multiple Dog
objects, each with a different name and age.
Example:
dog1 = Dog("Snoopy", 5) dog2 = Dog("Scooby Doo", 3) print(dog1.name) print(dog2.name) print(dog1.age) print(dog2.age)
Output:
Snoopy Scooby Doo 5 3
In the example above, dog1
and dog2
are two different instances of the Dog
class, each with its own name
and age
attribute. This demonstrates that instance attributes allow objects to have unique data.
Instance Methods
Instance methods are functions that are associated with an instance of a class (a.k.a object). They can access and modify the object’s attributes and perform operations using the object’s data.
In programming, a function is a reusable block of code designed to perform a specific task. Functions will be discussed in depth in the Functions chapter of this course.
Here is the basic syntax for defining an instance method within a class:
class ClassName: def instance_method_name(self, param1, param2, ...): ... # Method body with its code
def instance_method_name(self, param1, param2, ...)
: Defines an instance method. Theself
parameter is mandatory and must be the first parameter in the method definition. Other thanself
, the method can have zero or more other parameters, denoted asparam1, param2, ...
here. Parameters provide data that can be used in the method’s code.self
: Theself
parameter holds the method’s object itself. Usingself
you can access other attributes and methods of the object with the dot notation, e.g.self.attribute_name
. You can name theself
parameter with any valid identifier and then use that name to reference the object in your code. However, by convention it’s always “self"
. Using a name other thanself
might be confusing to anyone else looking at your code.
Instance methods are defined in a way similar to functions, but they always have at least one parameter: self
. The self
parameter represents the object on which the method is called.
Example:
class Dog: def __init__(self, name, age): self.name = name self.age = age def bark(self): return f"{self.name} says woof!" def birthday(self): self.age += 1 def get_treats(self, number_of_treats): return f"{self.name} got {number_of_treats} treats."
In the example above:
- The
Dog
class has two new instance methods (in addition to__init__()
):bark()
andbirthday()
. - The
bark()
method (line 6) returns a string with the dog’s name and a bark sound. - The
birthday()
method (line 9) increments the dog’s age by 1. - The
get_treats()
method (line 12) returns a string acknowledging the dog received the specified number of treats. This method also demonstrates the use of a parameters in a method (number_of_treats
).
To call an instance method, use dot notation on an object and place any arguments (i.e. the passed values) between the parentheses. Just don’t place a value for self
because Python does it implicitly for you.
Example:
my_dog = Dog("Snoopy", 5) print(my_dog.bark()) print(my_dog.get_treats(3)) my_dog.birthday() print(my_dog.age)
Output:
Snoopy says woof! Snoopy got 3 treats. 6
In the example above:
- A
Dog
object is assigned tomy_dog
. It has the name “Snoopy” and is. five years old (line 1). - The
bark()
method is called on themy_dog
object, returning “Snoopy says woof!” (line 3). - The
get_treats()
method is called onmy_dog
, returning “Snoopy got 3 treats” (line 5). - The
birthday()
method is called onmy_dog
, increasing its age by 1 (line 7).
Class Attributes
Class attributes are variables shared among all instances of a class. Unlike instance attributes, which are unique to each object, class attributes have the same value for every instance.
These attributes are useful for defining properties common to all instances of a class. They help save memory and provide a way to share data among all instances.
Class attributes are defined within the class but outside any methods. They are typically placed at the top of the class definition, immediately after the class header.
Here is the basic syntax for defining class attributes:
class ClassName: class_attribute = value # Class attribute # Rest of the class definition
class_attribute = value
: Defines a class attribute namedclass_attribute
with an initial value ofvalue
.
Example:
class Dog: species = "Canis familiaris" # Class attribute def __init__(self, name, age): self.name = name self.age = age def bark(self): return f"{self.name} says woof!" def birthday(self): self.age += 1 def get_treats(self, number_of_treats): return f"{self.name} got {number_of_treats} treats."
The example above adds the species
attribute to the familiar Dog
class from before (line 2). Since it specifies the name of the species, and all dogs are the same species, it’s fitting to have this attribute be a class attribute that is shared among all instances.
To access class attributes, you can use the dot notation with either the class name or an instance of the class, but it’s more common to use the class name to avoid confusion with instance attributes.
Example:
print(Dog.species) # Accessing class attribute via class name my_dog = Dog("Snoopy", 5) print(my_dog.species) # Accessing class attribute via an instance
Output:
Canis familiaris Canis familiaris
In the example above:
Dog.species
accesses the class attribute directly using the class name.my_dog.species
accesses the same class attribute using an instance of the class.
When an instance and a class have attributes of the same name, accessing the attribute from an object will return the instance attribute, if it exists; otherwise, it will return the class attribute.
Class Methods
Class methods are methods that are bound to the class rather than its instances. They can modify class state that applies across all instances of the class. Class methods have access to class attributes and other class methods, but not instance variables and methods.
These methods are marked with a @classmethod
decorator to indicate that they operate on the class itself, rather than on instances of the class. You can lean more about decorators and the @
syntax in the decorators lesson, but it’s not required for the discussion here. All you need to know now, is that placing @classmethod
before a method turns it into a class method.
Here is the basic syntax for defining a class method within a class:
class ClassName: @classmethod def class_method_name(cls, param1, param2, ...): ... # Method body
@classmethod
: The decorator that marks the method as a class method.cls
: The conventional name for the first parameter of a class method, which refers to the class itself. It’s similar to theself
parameter of an instance method, but instead of holding the object,cls
holds the class.
Example:
class Dog: species = "Canis familiaris" def __init__(self, name, age): self.name = name self.age = age @classmethod def change_species(cls, new_species): cls.species = new_species def bark(self): return f"{self.name} says woof!" def birthday(self): self.age += 1 def get_treats(self, number_of_treats): return f"{self.name} got {number_of_treats} treats."
In the example above:
- The
Dog
class has the class methodchange_species()
(line 9) decorated with@classmethod
. - Inside
change_species()
,cls.species = new_species
changes the class attributespecies
to a new value specified by the caller of the method (line 10).
To call a class method, you use dot notation on the class or instance. However, It’s more common to use the class since the class method logically belongs to it.
Example:
print(Dog.species) Dog.change_species("Snoopus fabulupus") print(Dog.species)
Output:
Canis familiaris Snoopus fabulupus
In the example above:
print(Dog.species)
outputs the current value of the class attributespecies
(line 1).Dog.change_species("Snoopus fabulupus")
calls the class methodchange_species()
and changes thespecies
class attribute to “Snoopus fabulupus” (line 2).print(Dog.species)
outputs the updated value of thespecies
class attribute (line 3).
Note that you cannot have an instance method and a class method defined with the same name in the same class. This may not be true for other programming languages, but is the case in Python. In fact, you cannot have any two methods of any type (including static methods discussed in the next section) with the same name. A method with the same name as a previous one in a class definition, simply overrides the first method and becomes the only one available.
Static Methods
Static methods are methods that belong to a class but do not have access to the class or instance attribute and methods. They are used for functions that logically belong to the class but do not need to access any class-specific data. Static methods are marked with a @staticmethod
decorator.
Unlike class methods that have the cls
parameter and instance methods that have the self
parameter, static methods do not have any default parameter. They operate just like regular functions but are part of the class’s namespace.
A namespace is a container (such as a class) that holds a set of identifiers (names) and ensures that all names are unique within it.
Here is the basic syntax for defining a static method within a class:
class ClassName: @staticmethod def static_method_name(param1, param2, ...): ... # Method body
@staticmethod
: The decorator that marks the method as a static method.
Example:
class Dog: species = "Canis familiaris" def __init__(self, name, age): self.name = name self.age = age @classmethod def change_species(cls, new_species): cls.species = new_species def bark(self): return f"{self.name} says woof!" def birthday(self): self.age += 1 def get_treats(self, number_of_treats): return f"{self.name} got {number_of_treats} treats." @staticmethod def is_puppy(age): return age < 1
In the example above:
- The
Dog
class has a static methodis_puppy()
(line 18) decorated with@staticmethod
. - Inside
is_puppy()
, it simply checks if the age provided is less than 1.
As with class methods, you can call a static method using the dot notation on the class or instance, but using the class is more common.
Example:
print(Dog.is_puppy(0.5)) print(Dog.is_puppy(2)) my_dog = Dog("Snoopy", 5) print(my_dog.is_puppy(0.5))
Output:
True False True
In the example above:
print(Dog.is_puppy(0.5))
calls the static methodis_puppy()
on theDog
class and checks if 0.5 is less than 1 (line 1). The result isTrue
.print(Dog.is_puppy(2))
calls the same method and checks if 2 is less than 1 (line 2). The result isFalse
.my_dog.is_puppy(0.5)
demonstrates that static methods can also be called on an instance of the class (line 5). The result isTrue
in this case as well.
Static methods are useful for utility functions that perform a task related to the class but do not need to access or modify class attributes or instance attributes. They help keep the code organized and encapsulate functionality within the relevant class.
Special Methods
Special methods allow you to define how objects of a class behave in various situations. They enable customization of behavior for built-in Python operations such as initialization, representation, comparison, and arithmetic. Special methods are also called magic methods or dunder methods (because their names are always surrounded by double underscores).
When defined, special methods are automatically called by Python to either get information from an object or have an object do something by running its own code.
You’ve already encountered one special method in this lesson, which is __init__()
. This method is called by Python when an object is created in order for the object to run its initialization code.
While there are many special methods in Python, the following subsections will discuss only two example to give you a taste of how they are used.
Special Method Example: The __str__() Method
The __str__()
method defines the string representation of an object. This method is called by the built-in (i.e. always made available by Python) function str()
, which converts a given object to a string. It’s also used by the print()
function, which prints to the console.
Example:
class Dog: def __init__(self, name, age): self.name = name self.age = age def __str__(self): return f"I'm a Dog, my name is {self.name} and I'm {self.age} years old."
In the example above, the __str__()
method (line 6) returns a string representation of the Dog
object (line 7).
When a string representation of a Dog
object is required, the __str__()
method implemented by Dog
provides it.
Example:
my_dog = Dog("Snoopy", 5) print(my_dog)
Output:
I'm a Dog, my name is Snoopy and I'm 5 years old.
In the example above, the print()
function calls __str__()
of the Dog
class behind the scenes (line 2) and prints what it returns to the console.
Special Method Example: The __eq__() Method
The __eq__
method defines the behavior of the equality comparison operator ==
for objects of the class. This method allows you to specify how objects should be compared for equality when the ==
operator is used.
Example:
class Dog: def __init__(self, name, age, owner): self.name = name self.age = age self.owner = owner def __eq__(self, other): return self.name == other.name and self.age == other.age
In the example above, the __eq__()
method implementation (line 6) compares Dog
objects based on their name
and age
attributes. Its only parameter aside from self
, is the other object in the comparison, given as the other
argument.
Although this Dog
class has another attribute, owner
, it is not used in the comparison. This demonstrates the flexibility of defining equality with __eq__()
and that it does not necessarily mean everything is the same.
The next example demonstrates how __eq__()
is used by the ==
operator.
Example:
dog1 = Dog("Snoopy", 5, "Bob") dog2 = Dog("Snoopy", 5, "Alice") dog3 = Dog("Scooby Doo", 3, "Charlie") print(dog1 == dog2) print(dog1 == dog3)
Output:
True False
The example above creates three Dog
objects. The first two, dog1
and dog2
(lines 1 and 2) have the same name and age, but different owners. They are therefore considered equal as defined by the __eq__()
method the previous example implemented. Their equality comparison therefore returns True
(line 5). The third Dog
object, dog3
(line 3), however, does not have the same name and age as the first two. Consequently, its comparison with dog1
returns False
(line 6).
Private Methods
Private methods are intended for internal use within a class. They are not meant to be accessed or called from outside the class.
Many programming languages prevent the usage of private methods outside the class by generating an error. However, Python does not enforce true private methods that way. Instead, it uses a naming convention to indicate that a method is intended to be private.
Naming Convention
To indicate that a method is private, its name should begin with an underscore (_
). This convention signals to other programmers that the method is for internal use only. By this convention, special methods, whose name is surrounded with double underscores, are also private.
For stricter privacy in your own methods, you can use a double underscore (__
) prefix. This triggers name mangling, where the interpreter changes the method name to include the class name, making it harder (though not impossible) to access from outside the class. (For now, this feature is left for you to explore further on your own.)
Using Single Underscore
The next two examples demonstrate using a single underscore to denote a private method.
Example:
class Dog: def __init__(self, name, age): self.name = name self.age = age def bark(self): return f"{self.name} says woof!" def _get_dog_years(self): return self.age * 7 def display_dog_years(self): dog_years = self._get_dog_years() return f"{self.name} is {dog_years} years old in dog years."
In this example:
- The
_get_dog_years()
method (line 9) is intended to be private and used only within the class. - The
display_dog_years()
method (line 12) calls_get_dog_years()
to get the dog’s age in dog years and returns a string.
Example:
my_dog = Dog("Snoopy", 5) print(my_dog.display_dog_years())
Output:
Snoopy is 35 years old in dog years.
In the example above, display_dog_years()
calls the _get_dog_years()
method internally, demonstrating the proper use of a private method.
Inheritance
Inheritance is a feature in object-oriented programming that allows a class to inherit attributes and methods from another class. The class that is inherited from is called the parent class (also called base class or superclass), and the class that inherits from it is called the child class (also called derived class or sublcass).
Why Use Inheritance?
Inheritance promotes code reusability and helps create a hierarchical relationship between classes. For example, if you have a general class Pet
that defines common attributes and methods for pets, you can create more specific classes like Dog
and Cat
that inherit from Pet
and add their own unique attributes and methods.
Defining a Child Class
To define a child class that inherits from a parent class, use the following syntax:
class ParentClass: ... # Parent class code class ChildClass(ParentClass): ... # Child class code
The ChildClass
inherits all attributes and methods from ParentClass
, which is specified in parentheses following the child class name in its definition (line 4).
The child class can also add new attributes and methods, or override ones that already exist in the parent class.
For the next example, let’s continue with our Dog
class and create a parent class Pet
.
Example:
class Pet: def __init__(self, name, age): self.name = name self.age = age def speak(self): raise NotImplementedError("Subclasses must implement this method")
In the example above:
- The
Pet
class has an__init__
method that initializes thename
andage
attributes (lines 2-4). - The
speak()
method is defined but raises aNotImplementedError
(line 7), indicating that subclasses should implement their own specific version of this method.
Now let’s create a Dog
class that inherits from Pet
.
Example:
class Dog(Pet): def __init__(self, name, age, breed): super().__init__(name, age) self.breed = breed def speak(self): return f"{self.name} says woof!"
In the example above:
- The
Dog
class inherits from thePet
class (line 1). - The
__init__()
method of theDog
class calls the__init__()
method of thePet
class usingsuper()
, to initialize thename
andage
attributes of the parent class (line 3). It then initializes thebreed
attribute that is added by theDog
class (line 4). - The
speak()
method (lines 6-7) overrides the method by the same name in thePet
parent class to provide a specific implementation for theDog
class.
Note: In Python, the super()
function calls the method of the parent class that has the same name as the method the code is currently in. Therefore, in the previous example, within Dog
‘s __init__()
method, super()
calls the __init__()
method of the Pet
class, which is the parent of Dog
.
Using Inheritance
You can create instances of the Dog
class and use its attributes and methods, including those inherited from the Pet
class.
Example:
my_dog = Dog("Snoopy", 5, "Beagle") print(my_dog.name) # Inherited from Pet print(my_dog.age) # Inherited from Pet print(my_dog.breed) # Defined in Dog print(my_dog.speak()) # Overridden in Dog
Output:
Snoopy 5 Beagle Snoopy says woof!
In the example above:
my_dog
is an instance of theDog
class with thename
“Snoopy”,age
5, andbreed
“Beagle” (line 1).- The
name
andage
attributes are inherited from thePet
class (lines 2-3). - The
breed
attribute is defined in theDog
class (line 4). - The
speak()
method is overridden in theDog
class to provide a specific implementation for dogs (line 5).
Overriding Methods
When a child class provides a specific implementation for a method that is already defined in its parent class, it is called method overriding. This allows the child class to customize or extend the behavior of the parent class method.
In the previous example, the speak()
method in the Dog
class overrides the speak()
method in the Pet
class.
Extending the Parent Class
In addition to overriding methods, you can also add new methods and attributes to the child class that are not present in the parent class.
Let’s extend the Dog
class with a new method, fetch()
.
Example:
class Dog(Pet): def __init__(self, name, age, breed): super().__init__(name, age) self.breed = breed def speak(self): return f"{self.name} says woof!" def fetch(self, item): return f"{self.name} fetched the {item}!"
Example:
my_dog = Dog("Snoopy", 5, "Beagle") print(my_dog.fetch("ball"))
Output:
Snoopy fetched the ball!
In the example above, the fetch()
method is called on the my_dog
instance, demonstrating the new functionality added to the Dog
class.
Multiple Inheritance
Python supports multiple inheritance, where a class can inherit from more than one parent class. This allows a child class to combine attributes and methods from multiple parent classes.
To define a child class that inherits from a parent class, use the following syntax:
class Parent1Class: ... # Parent 1 class code class Parent2Class: ... # Parent 2 class code class ChildClass(Parent1Class, ParentClass): ... # Child class code
In the multiple inheritance syntax, the parent classes are specified in a comma-separated list within the parentheses following the child class name (line 7).
Example:
class Pet: def __init__(self, name, age): self.name = name self.age = age def speak(self): raise NotImplementedError("Subclasses must implement this method") class Canine: def __init__(self, species): self.species = species def howl(self): return f"{self.species} is howling!" class Dog(Pet, Canine): def __init__(self, name, age, breed): Pet.__init__(self, name, age) Canine.__init__(self, "Canis familiaris") self.breed = breed def speak(self): return f"{self.name} says woof!"
In the example above:
- The
Dog
class inherits from both thePet
andCanine
classes (line 16). - The
__init__()
method of theDog
class calls the__init__()
methods of both parent classes using the dot notation to initialize their attributes (lines 17-18).
Example:
my_dog = Dog("Snoopy", 5, "Beagle") print(my_dog.name) # Inherited from Pet print(my_dog.age) # Inherited from Pet print(my_dog.species) # Inherited from Canine print(my_dog.speak()) # Overridden in Dog print(my_dog.howl()) # Inherited from Canine
Output:
Snoopy 5 Canis familiaris Snoopy says woof! Canis familiaris is howling!
In the example above:
my_dog
is an instance of theDog
class with attributes and methods inherited from both thePet
andCanine
classes (line 1).- The
name
andage
attributes are inherited from thePet
class (lines 2-3). - The
species
attribute andhowl
method are inherited from theCanine
class (lines 4 and 6). - The
speak
method is overridden in theDog
class (line 5).
Summary & Reference for Python Classes and Objects
An object is a collection of data and methods that operate on that data.
A class is a blueprint for creating objects, which are instance of a class.
To define a class, use the class
keyword followed by the class name, a colon, and a code block that defines it.
class Dog: ... # The code block that defines the class goes here.
To create an object (instance) of a class, use parentheses after the class name.
my_dog = Dog()
Use the __init__()
method to initializes a new instance of the class and creates its instance attributes. __init__()
is called automatically by Python when an object is created.
class Dog: def __init__(self, name): self.name = name
To pass values to the __init__() method, place them in the parentheses, separated by commas, when you create an object.
my_dog = Dog("Snoopy")
Instance attributes store data unique to each object. Access those using the dot notation.
print(my_dog.name) # --> Snoopy
Instance methods are functions that are associated with an object. To define instance methods, use the def
keyword. The first parameter is self
and it’s used to hold the object itself.
class Dog: def __init__(self, name): self.name = name def bark(self): print(f"{self.name} says woof!")
To call an instance method on an object, use the dot notation. Don’t pass an argument for self
because Python does it automatically.
my_dog.bark() # --> Snoopy says woof!
Class attributes are shared across all instances of the class. Define those within the class outside of any method.
class Dog: species = "Canis familiaris"
To access class attributes use the class name or an instance.
print(Dog.species) # --> Canis familiaris print(my_dog.species) # --> Canis familiaris
Class methods are methods that are bound to the class rather than its instances, and are defined with the @classmethod
decorator. They receive the cls
parameter, which holds the class.
class Dog: species = "Canis familiaris" @classmethod def common_species(cls): return cls.species
Static methods are methods that belong to a class but do not have access to the class or instance attribute and methods. They are defined with the @staticmethod
decorator.
class Dog: @staticmethod def bark_sound(): return "Woof!"
Static methods can be called using the class name or an instance.
print(Dog.bark_sound()) # --> Woof! print(my_dog.bark_sound()) # --> Woof!
Special methods (a.k.a magic or methods or dunder methods) allow you to define and customize how objects of a class behave in various situations. They are always named with a double underscore (__
) on each side.
class Dog: def __init__(self, name, age): self.name = name self.age = age # __str__() defines the string representation of an object. def __str__(self): return f"I'm a Dog, my name is {self.name} and I'm {self.age} years old."
Private methods are methods intended for internal use within a class. They are not meant to be accessed or called from outside the class.
Unlike other programming languages, Python does not restrict access to private methods. Instead, it uses a convention of starting a method name with an underscore (_
) to signal programmers that a method should be treated as private.
Inheritance allows a class to inherit attributes and methods from another class. The class that is inherited from is called the parent class (or base class), and the class that inherits from it is called the child class (or derived class).
To define a child class that inherits from a parent class, specify the name of the parent class in parentheses after the name of the child class in its definition.
class ParentClass: ... # Parent class code class ChildClass(ParentClass): ... # Child class code
Use the super()
function to call the method of the parent class that has the same name as the method the code is currently in.
class Dog(Pet): def __init__(self, name, age, breed): super().__init__(name, age) # Calls the __init__() method of the parent class (Pet). self.breed = breed def speak(self): return f"{self.name} says woof!"
Python supports multiple inheritance, where a class can inherit from more than one parent class.
In the multiple inheritance syntax, the parent classes are specified in a comma-separated list within the parentheses following the child class name.
class Parent1Class: ... # Parent 1 class code class Parent2Class: ... # Parent 2 class code class ChildClass(Parent1Class, ParentClass): ... # Child class code