Advanced Python Programming
Hoang-Giang Cao (高黃江)
Sep 2023
4 Pillars of OOP
Basic Python
Homework 2
Basic Python
Homework 1
Basic Python
Midterm
Basic Python
Homework 3
Basic Python
Thanksgiving event
2 Extra Homeworks - Not required to do. But, attending each of them:
4 Pillars of OOP
4 Pillars of OOP
抽象
封裝
繼承
多型
Class
class Car()
The concept of a car
pattern/design
brand
color
shape
length
.
etc
move ()
steering ()
stop ()
open_light()
.
etc
Attribute/property
Method/behaviors
Difference instance has different value for each attribute: different in appearance
All instances of the same class has the same method/behaviors
Each car has different name, color, shape. But all cars can move, steering, stop, open_light, etc
Instances/object
Attribute
Method
Abstraction (抽象)
抽象在物件導向程式設計中隱藏成員屬性與方法實作細節的機制,讓使用者能方便地使用功能而不需要了解細節
Abstraction
You press the “Power” button
to turn on the computer
without caring about the mechanism behind making it actually work
interface
operate
“Power” button
Abstraction
What we need to know is that pressing the Power button, and the PC will turn on, go to the OS
How does it work (hardwares, software), we don’t (really need to) know
“Power” button
Display to the screen
mechanism behind
Abstraction
Hidden mechanism behind
=
Return the result
3/7 + 7/3 = ?
Calculator
Abstraction
mechanism behind
Function remove_oldest_car() to remove the oldest car
List of cars
List of cars
10 years
15 years
30 years
20 years
5 years
interface
operator
hidden
Abstraction
username
password
birth_year
Attribute
Method
amount_TWD
amount_USD
check_valid_deposit()
check_valid_pass()
Other internal methods
get_total()
Abstraction
username
password
birth_year
Attribute
Method
amount_TWD
amount_USD
check_valid_deposit()
check_valid_pass()
Other internal methods
get_total()
amount_TWD
+
amount_USD*30
User
Client
Frontend
Call the function
Get the return result
Abstraction
Encapsulation
Back-end
Front-end
Client
User
Send request/input
Get result/output
Internet
Blackbox to the user/client/front-end
Database
API
(public functions)
backend
Abstraction
Encapsulation
Back-end
Front-end
Client
User
Send request/input
Get result/output
Internet
Blackbox to the user/client/front-end
API
(public functions)
Database
Bank account implementation
class BankAccount:
withdraw_rate = 0.005 #0.5#
def __init__(self,username,password):
#userbank information
self.username = username
self.password = password
#bank account
self.account_TWD =0
self.transactions=[] #list of transaction
Class Attributes:
Instance Attributes (defined in the __init__ constructor):
class BankAccount:
withdraw_rate = 0.005 #0.5#
def __init__(self,username,password):
#userbank information
self.username = username
self.password = password
#bank account
self.account_TWD =0
self.transactions=[] #list of transaction
def withdraw(self,request_amount_TWD):
withdraw_fee = request_amount_TWD*BankAccount.withdraw_rate
if (self.account_TWD >= request_amount_TWD+withdraw_fee):
print("Succesfull transaction!")
print("Withdraw ",request_amount_TWD,"NTD. withdraw free:",withdraw_fee,"NTD")
self.account_TWD -= (request_amount_TWD+withdraw_fee)
else:
print("Insufficient money! Transaction Failed!"
#Client side # Bank Officer#withdraw
print("Before transaction:", acc_1.account_TWD,"NTD")
acc_1.withdraw(2000)
print("After transaction:", acc_1.account_TWD,"NTD")
#user create and deposit
acc_1 = BankAccount("KO","1234")
#deposit
acc_1.account_TWD = 3000
Class implementation
Backend
You only need to call the function, no need to know how does it work (back-end responsibility)
Bank Officer
Client
User
Deposit (Init)
class BankAccount:
withdraw_rate = 0.005 #0.5#
def __init__(self,username,password):
#userbank information
self.username = username
self.password = password
#bank account
self.account_TWD =0
self.transactions=[] #list of transaction
def withdraw(self,request_amount_TWD):
withdraw_fee = request_amount_TWD*BankAccount.withdraw_rate
if (self.account_TWD >= request_amount_TWD+withdraw_fee):
print("Succesfull transaction!")
print("Withdraw ",request_amount_TWD,"NTD. withdraw free:",withdraw_fee,"NTD")
self.account_TWD -= (request_amount_TWD+withdraw_fee)
else:
print("Insufficient money! Transaction Failed!"
#Client side # Bank Officer#withdraw
print("Before transaction:", acc_1.account_TWD,"NTD")
acc_1.withdraw(1000)
print("After transaction:", acc_1.account_TWD,"NTD")
#user create and deposit
acc_1 = BankAccount("KO","1234")
#deposit
acc_1.account_TWD = 3000
Class implementation
Backend
Bank Officer
Client
User
Deposit (init)
class BankAccount:
withdraw_rate = 0.01 #0.5#
def __init__(self,username,password):
#userbank information
self.username = username
self.password = password
#bank account
self.account_TWD =0
self.transactions=[] #list of transaction
def withdraw(self,request_amount_TWD):
withdraw_fee = request_amount_TWD*BankAccount.withdraw_rate
if (self.account_TWD >= request_amount_TWD+withdraw_fee):
print("Succesfull transaction!")
print("Withdraw ",request_amount_TWD,"NTD. withdraw free:",withdraw_fee,"NTD")
self.account_TWD -= (request_amount_TWD+withdraw_fee)
else:
print("Insufficient money! Transaction Failed!"
#Client side # Bank Officer#withdraw
print("Before transaction:", acc_1.account_TWD,"NTD")
acc_1.withdraw(1000)
print("After transaction:", acc_1.account_TWD,"NTD")
#user create and deposit
acc_1 = BankAccount("KO","1234")
#deposit
acc_1.account_TWD = 3000
Class implementation
Backend
Bank Officer
Client
User
Deposit (init)
If the fee rate change, the front-end still be correct
Nothing change in the code of front-end
class BankAccount:
withdraw_rate = 0.01 #0.5#
def __init__(self,username,password):
#userbank information
self.username = username
self.password = password
#bank account
self.account_TWD =0
self.transactions=[] #list of transaction
def withdraw(self,request_amount_TWD):
withdraw_fee = request_amount_TWD*BankAccount.withdraw_rate
if (self.account_TWD >= request_amount_TWD+withdraw_fee):
print("Succesfull transaction!")
print("Withdraw ",request_amount_TWD,"NTD. withdraw free:",withdraw_fee,"NTD")
self.account_TWD -= (request_amount_TWD+withdraw_fee)
else:
print("Insufficient money! Transaction Failed!"
#Client side # Bank Officer#withdraw
print("Before transaction:", acc_1.account_TWD,"NTD")
acc_1.withdraw(1000)
print("After transaction:", acc_1.account_TWD,"NTD")
#user create and deposit
acc_1 = BankAccount("KO","1234")
#deposit
acc_1.account_TWD = 3000
Class implementation
Backend
Bank Officer
Client
User
Deposit
Or if we modify/update anything inside the withdraw function, the client slide still be the same
class BankAccount:
def __init__(self,username,password):
#userbank information
self.username = username
self.password = password
#bank account
self.account_TWD =0
self.transactions=[] #list of transaction
#make a withdraw
withdraw_rate = 0.05
request_amount_TWD = 1000
#Client side # Bank Officer#withdraw
print("Before transaction:", acc_1.account_TWD,"NTD")
withdraw_fee = request_amount_TWD*withdraw_rate
if (acc_1.account_TWD >= request_amount_TWD+withdraw_fee):
print("Succesfull transaction!")
print("Withdraw ",request_amount_TWD,"NTD. withdraw free:",withdraw_fee,"NTD")
acc_1.account_TWD -= (request_amount_TWD+withdraw_fee)
else:
print("Insufficient money! Transaction Failed!")
print("After transaction:", acc_1.account_TWD,"NTD")
Class implementation
Backend
Bank Officer
Client
User
If we do the code in the client (front-end), client need to update by themself (not convenient, or not permission)
Abstraction
Encapsulation
Encapsulation(封裝)
Capsule
Encapsulation
Binding attribute and method in to a single unit
封裝是物件導向程式設計中隱藏資料與函式實作的技巧。
Encapsulation
username
password
birth_year
Attribute
Method
amount_TWD
amount_USD
check_valid_deposit()
check_valid_pass()
Other internal methods
deposit_TWD()
deposit_USD()
set_password()
get_total()
Capsule
Encapsulation
Binding attribute and method in to a single unit
Problem of protecting data
username
password
birth_year
Attribute
Method
amount_TWD
amount_USD
check_valid_deposit()
check_valid_pass()
Other internal methods
deposit_TWD()
deposit_USD()
set_password()
get_total()
Front-end
Client
User
Send request/input
Get result/output
Should not happen
Problem of protecting data
username
password
birth_year
Attribute
Method
amount_TWD
amount_USD
check_valid_deposit()
check_valid_pass()
Other internal methods
deposit_TWD()
deposit_USD()
set_password()
get_total()
Front-end
Client
User
Send request/input
Get result/output
Should not happen
Bank account implementation
class BankAccount:
withdraw_rate = 0.005 #0.5#
def __init__(self,username,password):
#userbank information
self.username = username
self.password = password
#bank account
self.account_TWD =0
self.transactions=[] #list of transaction
Class Attributes:
Instance Attributes (defined in the __init__ constructor):
Encapsulation
Bank officer 1
(client)
username
password
account_TWD
Get user.password??
Admin created
Or user register
database
Data protection
Username | Password |
KO | 1234 |
Alex | ILoveYou |
Tom | KissYou |
BankAccount
Bank officer 1
(client)
username
password
account_TWD
Admin created
Or user register
database
Client/frontend
Server/backend
Database
Get user.password??
Username | Password |
KO | 1234 |
Alex | ILoveYou |
Tom | KissYou |
result
BankAccount
Username | Password |
KO | 1234 |
Alex | ILoveYou |
Tom | KissYou |
Bank officer 1
(client)
username
password
account_TWD
Admin created
Or user register
database
Client/frontend
Server/backend
Database
result
NO PERMISSION TO DO THAT!!!!
Get user.password??
BankAccount
Encapsulation
username
password
birth_year
Attribute
Method
amount_TWD
amount_USD
Abstraction
check_valid_deposit()
check_valid_pass()
Other internal methods
deposit_TWD()
deposit_USD()
set_password()
get_total()
User access
User access
X
Sensitive information
Abstraction
Encapsulation
Attributes
Methods
Front-end
Client
User
Send request/input
Get result/output
Internet
API
(public functions)
Database
Encapsulation
username
password
birth_year
Attribute
Method
amount_TWD
amount_USD
Abstraction
check_valid_deposit()
check_valid_pass()
Other internal methods
deposit_TWD()
deposit_USD()
set_password()
get_total()
User access
User access
X
Encapsulation
Abstraction
Front-end
Client
User
Internet
Blackbox to the user/client/front-end
API
(public functions)
Database
Attribute
(data)
Methods
(functions)
Send request/input
Get result/output
Encapsulation
Abstraction
Front-end
Client
User
Send request/input
Get result/output
Internet
Blackbox to the user/client/front-end
API
(public functions)
Database
Attribute
(data)
Methods
(functions)
Encapsulation
Encapsulation
Bank officer 1
(client)
username
password
account_TWD
Get user.password??
Admin created
Or user register
database
Data protection
Username | Password |
KO | 1234 |
Alex | ILoveYou |
Tom | KissYou |
BankAccount
Bank officer 1
(client)
username
password
account_TWD
Admin created
Or user register
database
Client/frontend
Server/backend
Database
Get user.password??
Username | Password |
KO | 1234 |
Alex | ILoveYou |
Tom | KissYou |
result
BankAccount
Abstraction
Encapsulation
Attributes
Methods
Front-end
Client
User
Send request/input
Get result/output
Internet
API
(public functions)
Database
Username | Password |
KO | 1234 |
Alex | ILoveYou |
Tom | KissYou |
Bank officer 1
(client)
username
password
account_TWD
Admin created
Or user register
database
Client/frontend
Server/backend
Database
result
NO PERMISSION TO DO THAT!!!!
Get user.password??
BankAccount
Encapsulation
Abstraction
Front-end
Client
User
Internet
Blackbox to the user/client/front-end
API
(public functions)
Database
Attribute
(data)
Methods
(functions)
Send request/input
Get result/output
Encapsulation
Abstraction
Front-end
Client
User
Send request/input
Get result/output
Internet
Blackbox to the user/client/front-end
API
(public functions)
Database
Attribute
(data)
Methods
(functions)
Username | Password |
KO | 1234 |
Alex | ILoveYou |
Tom | KissYou |
Bank officer 1
(client)
username
password
account_TWD
Admin created
Or user register
database
Client/frontend
Server/backend
Database
Get user.password??
Set password be private
self.__password
Get error result
NO PERMISSION TO DO THAT!!!!
BankAccount
username
password
account_TWD = 20
transaction[]
Transaction | Amount |
1 | 5 |
2 | 10 |
3 | 5 |
= 20
account_TWD
consistency
Transaction | Amount |
1 | 5 |
2 | 10 |
3 | 5 |
database
Bank officer 1
Encapsulation
BankAccount
username
password
account_TWD = 20
transaction[]
Transaction | Amount |
1 | 5 |
2 | 10 |
3 | 5 |
= 20
account_TWD
consistency
Bank officer 1
Data consistency
BankAccount
username
password
account_TWD = 20
transaction[]
Transaction | Amount |
1 | 5 |
2 | 10 |
3 | 5 |
= 20
account_TWD
consistent
Bank officer 1
Transaction | Amount |
1 | 5 |
2 | 10 |
3 | 5 |
database
consistent
username
password
account_TWD = 20
transaction[]
user_1.account_TWD = 1000000???
BankAccount
Transaction | Amount |
1 | 5 |
2 | 10 |
3 | 5 |
= 1000000
account_TWD
Bank officer 1
Transaction | Amount |
1 | 5 |
2 | 10 |
3 | 5 |
database
username
password
account_TWD = 20
transaction[]
user_1.account_TWD = 1000000???
BankAccount
Transaction | Amount |
1 | 5 |
2 | 10 |
3 | 5 |
= 1000000
account_TWD
inconsistent!!!
Bank officer 1
Transaction | Amount |
1 | 5 |
2 | 10 |
3 | 5 |
database
inconsistent!!!
NO PERMISSION TO DO THAT!!!!
username
password
account_TWD = 20
transaction[]
BankAccount
Transaction | Amount |
1 | 5 |
2 | 10 |
= 20
account_TWD
inconsistent!!!
Bank officer 1
Transaction | Amount |
1 | 5 |
2 | 10 |
database
Forget to add transaction
Mising adding transaction
inconsistent!!!
username
password
account_TWD = 20
transaction[]
BankAccount
Transaction | Amount |
1 | 5 |
2 | 10 |
3 | 5 |
= 15
account_TWD
inconsistent!!!
Bank officer 1
Transaction | Amount |
1 | 5 |
2 | 10 |
3 | 5 |
database
Forget to update total amount
inconsistent!!!
Missing update account_TWD
username
password
account_TWD = 20
transaction[]
BankAccount
Bank officer 1
API
(public functions)
Make attributes be private, provide public functions (API) for user to operate
No more direct access to the attribute
Solution
So we need the deposit function
To ensure the consistency of adding and updating
username
password
account_TWD = 20
transaction[]
BankAccount
Bank officer 1
API
(public functions)
Make attributes be private, provide public functions (API) for user to operate
Solution
Use the provided pubic function to deposit money
Transaction | Amount |
1 | 5 |
2 | 10 |
3 | 15 |
account_TWD = 5
account_TWD = 15
account_TWD = 20
Transaction | Amount |
1 | 5 |
2 | 10 |
3 | 15 |
account_TWD = 5
account_TWD = 15
account_TWD = 20
Alway consistent
Data validation
Data validation
Direct access to the attribute
Access through provided public function
Invalid data
Make attributes be private, provide public functions (API) for user to operate
Transaction | Amount |
1 | 5 |
2 | 10 |
3 | 15 |
account_TWD = 5
account_TWD = 15
account_TWD = 20
Alway consistent
How to access the needed attributes: account_TWD, transactions?
If they are private?
No more direct access to the attribute
Provided some public function that allow the user get the private attributes
Transaction | Amount |
1 | 5 |
2 | 10 |
3 | 15 |
account_TWD = 5
account_TWD = 15
account_TWD = 20
Alway consistent
How to access the needed attributes: account_TWD, transactions?
If they are private?
Access private attribute through public functions (API) (similar to getter/setter in c++)
Solution
You provided some public function that allow the user get the private attributes
Client can get value, but can not set or assign value
Encapsulation(封裝)
封裝是物件導向程式設計中隱藏資料與函式實作的技巧。