Object-oriented programming (OOP) is a widely used programming paradigm that reduces development times—making it easier to read, reuse, and maintain your code. OOP shifts the focus from thinking about code as a sequence of actions to looking at your program as a collection of objects that interact with each other. In this course, you’ll learn how to create classes, which act as the blueprints for every object in Python. You’ll then leverage principles called inheritance and polymorphism to reuse and optimize code.
By Alex Yarosh, Curriculum Developer @ Cockroach Labs
Learn what object-oriented programming (OOP) is, how it differs from procedural-programming, and how it can be applied. Define your own classes, and create methods, attributes, and constructors.
- Best practices
- Initialize attributes in
__init__()
- Naming: CamelCase for class, lower_snake_case for functions and attributes
- Keep self as self
- Initialize attributes in
Inheritance and polymorphism are the core concepts of OOP that enable efficient and consistent code reuse. Inherit from a class, customize and redefine methods, and review the differences between class-level data and instance-level data.
- Core principles of OOP
- Inheritance: Extending functionality of existing code
- Polymorphism: Creating a unifed interface
- Encapsulation: Bundling of data and methods
- Instance-level data
- Class-level data
- Class methods
- Alternative constructors
- Inheritance: "is-a" relationship
class BankAccount:
def __init__(self, balance):
self.balance = balance
def withdraw(self, amount):
self.balance -=amount
# Empty class inherited from BankAccount
class SavingsAccount(BankAccount):
# Constructor speficially for SavingsAccount with an additional parameter
def __init__(self, balance, interest_rate):
# Call the parent constructor using ClassName.__init__()
BankAccount.__init__(self, balance)
# <--- self is a SavingsAccount but also a BankAccount
# Add more functionality
self.interest_rate = interest_rate
Make sure that objects that store the same data are considered equal, define and customize string representations of objects, and even create new error types. Further customize your classes to make them work more like standard Python data types.
- Operator overloading
- Object equality:
__eq__()
- Comparison of objects:
__ne__()
, etc. - Printing an object:
__str__()
and__repr__()
- Object equality:
- Exceptions
- Raising and handling exceptions
- Exceptions are classes, standard and custom exceptions
Design classes for inheritance. Python has private attributes? Control attribute access?
- Polymorphism
- Using a unified interface to operate on objects of different classes
- Liskov substitution principle
Base class should be interchangeable with any of its
subclasses without altering any properties of the program
- Restricting access
- Naming conventions
- internal attributes:
obj._att_name , obj._method_name()
- pseudoprivate attributes:
obj.__attr_name , obj.__method_name()
- Name mangling: obj.__attr_name is interpreted as obj._MyClass__attr_name
- Leading and trailing __ are only used for built-in Python methods
__init__()
,__repr__()
- internal attributes:
- Use @property to customize access
- User-facing: behave like attributes
- Developer-facing: give control of access
- Other possibilities
- Do not add
@attr.setter
: Create a read-only property - Add
@attr.getter
: Use for the method that is called when the property's value is retrieved - Add
@attr.deleter
: Use for the method that is called when the property is deleted using del
- Do not add
- Overriding
__getattr__()
and__setattr__()
- Naming conventions