Skip to content

Instantly share code, notes, and snippets.

@misho-kr
Last active September 18, 2023 04:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save misho-kr/4aa4a8a2dcc5a413f1a51b13e23eda3a to your computer and use it in GitHub Desktop.
Save misho-kr/4aa4a8a2dcc5a413f1a51b13e23eda3a to your computer and use it in GitHub Desktop.
Summary of "Object-Oriented Programming in Python" from Datacamp.Org

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

OOP Fundamentals

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

Inheritance and Polymorphism

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

Integrating with Standard Python

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__()
  • Exceptions
    • Raising and handling exceptions
    • Exceptions are classes, standard and custom exceptions

Best Practices of Class Design

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__()
    • 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
    • Overriding __getattr__() and __setattr__()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment