Instance and class
data
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Alex Yarosh
Content Quality Analyst @ DataCamp
Core principles of OOP
Inheritance:
Extending functionality of existing code
Polymorphism:
Creating a uni ed interface
Encapsulation:
Bundling of data and methods
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Instance-level data
class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary
emp1 = Employee("Teo Mille", 50000)
emp2 = Employee("Marta Popov", 65000)
name , salary are instance a ributes
self binds to an instance
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Class-level data
Data shared among all instances of a class
De ne class a ributes in the body of class
class MyClass:
# Define a class attribute
CLASS_ATTR_NAME = attr_value
"Global variable" within the class
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Class-level data
class Employee: MIN_SALARY is shared among all instances
# Define a class attribute
Don't use self to de ne class a ribute
MIN_SALARY = 30000 #<--- no self.
def __init__(self, name, salary): use ClassName.ATTR_NAME to access the
self.name = name
class a ribute value
# Use class name to access class attribute
if salary >= Employee.MIN_SALARY:
self.salary = salary
else:
self.salary = Employee.MIN_SALARY
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Class-level data
class Employee: emp1 = Employee("TBD", 40000)
# Define a class attribute print(emp1.MIN_SALARY)
MIN_SALARY = 30000
def __init__(self, name, salary):
30000
self.name = name
# Use class name to access class attribute
emp2 = Employee("TBD", 60000)
if salary >= Employee.MIN_SALARY:
print(emp2.MIN_SALARY)
self.salary = salary
else:
self.salary = Employee.MIN_SALARY 30000
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Why use class attributes?
Global constants related to the class
minimal/maximal values for a ributes
commonly used values and constants, e.g. pi for a Circle class
...
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Class methods
Methods are already "shared": same code for every instance
Class methods can't use instance-level data
class MyClass:
@classmethod # <---use decorator to declare a class method
def my_awesome_method(cls, args...): # <---cls argument refers to the class
# Do stuff here
# Can't use any instance attributes :(
MyClass.my_awesome_method(args...)
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Alternative constructors
class Employee: Can only have one __init__()
MIN_SALARY = 30000
def __init__(self, name, salary=30000):
self.name = name
if salary >= Employee.MIN_SALARY:
self.salary = salary
else:
self.salary = Employee.MIN_SALARY
Use class methods to create objects
@classmethod
def from_file(cls, filename): Use return to return an object
with open(filename, "r") as f:
cls(...) will call __init__(...)
name = f.readline()
return cls(name)
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Alternative constructors
class Employee:
MIN_SALARY = 30000
def __init__(self, name, salary=30000):
self.name = name
if salary >= Employee.MIN_SALARY:
self.salary = salary
else:
# Create an employee without calling Employee()
self.salary = Employee.MIN_SALARY
emp = Employee.from_file("employee_data.txt")
type(emp)
@classmethod
def from_file(cls, filename):
with open(filename, "r") as f: __main__.Employee
name = f.readline()
return cls(name)
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Let's practice!
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Class inheritance
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Alex Yarosh
Content Quality Analyst @ DataCamp
Code reuse
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Code reuse
1. Someone has already done it
Modules are great for xed functionality
OOP is great for customizing functionality
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Code reuse
1. Someone has already done it
2. DRY: Don't Repeat Yourself
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Code reuse
1. Someone has already done it
2. DRY: Don't Repeat Yourself
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Inheritance
New class functionality = Old class functionality + extra
OBJECT-ORIENTED PROGRAMMING IN PYTHON
OBJECT-ORIENTED PROGRAMMING IN PYTHON
OBJECT-ORIENTED PROGRAMMING IN PYTHON
OBJECT-ORIENTED PROGRAMMING IN PYTHON
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Implementing class inheritance
class BankAccount: class MyChild(MyParent):
def __init__(self, balance): # Do stuff here
self.balance = balance
MyParent : class whose functionality is
def withdraw(self, amount): being extended/inherited
self.balance -= amount
MyChild : class that will inherit the
functionality and add more
# Empty class inherited from BankAccount
class SavingsAccount(BankAccount):
pass
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Child class has all of the the parent data
# Constructor inherited from BankAccount
savings_acct = SavingsAccount(1000)
type(savings_acct)
__main__.SavingsAccount
# Attribute inherited from BankAccount
savings_acct.balance
1000
# Method inherited from BankAccount
savings_acct.withdraw(300)
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Inheritance: "is-a" relationship
A SavingsAccount is a BankAccount
(possibly with special features)
savings_acct = SavingsAccount(1000) acct = BankAccount(500)
isinstance(savings_acct, SavingsAccount) isinstance(acct,SavingsAccount)
True False
isinstance(savings_acct, BankAccount) isinstance(acct,BankAccount)
True True
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Let's practice!
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Customizing
functionality via
inheritance
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Alex Yarosh
Content Quality Analyst @ DataCamp
OBJECT-ORIENTED PROGRAMMING IN PYTHON
What we have so far
class BankAccount:
def __init__(self, balance):
self.balance = balance
def withdraw(self, amount):
self.balance -=amount
# Empty class inherited from BankAccount
class SavingsAccount(BankAccount):
pass
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Customizing constructors
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
Can run constructor of the parent class rst by Parent.__init__(self, args...)
Add more functionality
Don't have to call the parent constructors
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Create objects with a customized constructor
# Construct the object using the new constructor
acct = SavingsAccount(1000, 0.03)
acct.interest_rate
0.03
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Adding functionality
Add methods as usual
Can use the data from both the parent and the child class
class SavingsAccount(BankAccount):
def __init__(self, balance, interest_rate):
BankAccount.__init__(self, balance)
self.interest_rate = interest_rate
# New functionality
def compute_interest(self, n_periods = 1):
return self.balance * ( (1 + self.interest_rate) ** n_periods - 1)
OBJECT-ORIENTED PROGRAMMING IN PYTHON
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Customizing functionality
class CheckingAccount(BankAccount): Can change the signature (add
def __init__(self, balance, limit): parameters)
BankAccount.__init__(self, content)
self.limit = limit Use Parent.method(self, args...) to call
def deposit(self, amount):
self.balance += amount
a method from the parent class
def withdraw(self, amount, fee=0):
if fee <= self.limit:
BankAccount.withdraw(self, amount - fee)
else:
BankAccount.withdraw(self,
amount - self.limit)
OBJECT-ORIENTED PROGRAMMING IN PYTHON
check_acct = CheckingAccount(1000, 25) bank_acct = BankAccount(1000)
# Will call withdraw from CheckingAccount # Will call withdraw from BankAccount
check_acct.withdraw(200) bank_acct.withdraw(200)
# Will call withdraw from CheckingAccount # Will produce an error
check_acct.withdraw(200, fee=15) bank_acct.withdraw(200, fee=15)
TypeError: withdraw() got an unexpected
keyword argument 'fee'
OBJECT-ORIENTED PROGRAMMING IN PYTHON
Let's practice!
OBJECT-ORIENTED PROGRAMMING IN PYTHON