測試奇譚,BUG不見。
這一場主講python的物件導向部分——封裝、多型和繼承。
目的:掌握Python物件導向的三個核心概念。
封裝
01 什麼是封裝?
封裝的目的是,保護隱私。通俗的講:不想讓別人知道你的東西。
於是,便有了兩個概念:普通屬性(變數)和私有屬性(變數)。
02 為什麼要用封裝?
當你不希望外界可以直接修改一些資料時。
比如使用者的身份證號等資訊屬於使用者的隱私,肯定不能直接暴露給外界直接訪問或修改,那麼就不能把它作為普通屬性,應該作為私有屬性。
03 怎麼使用封裝?
看下面這個例子就夠了。
# !/usr/bin/python
# -*- coding:utf-8 -*-
class User:
def __init__(self, name, id_card):
# 普通屬性
self.name = name
# 私有屬性(雙下劃線)
self.__id_card = id_card
def get_id_card(self):
return self.__id_card
class Student(User):
def init(self, name, id_card):
# 普通屬性
self.name = name
# 私有屬性
self.__id_card = id_card
# 例項化一個User類
user = User('張三', 511011199505050101)
stu = Student('李四', 511011199505050808)
#print(user.__id_card)
# 不能直接訪問私有屬性,會報錯:AttributeError: 'User' object has no attribute '__age'
print(user.get_id_card())
# 可以通過成員方法去訪問私有屬性
print(user._User__id_card)
# 也可以通過 “_類名__私有屬性名” 進行訪問
多型
01 什麼是多型?
- 多型指同一個實體同時具有多種形式。
- 它是物件導向程式設計(OOP)的一個重要特徵。
- 同一操作作用於不同的物件,可以有不同的解釋,產生不同的執行結果。
- 多型一般要通過繼承和重寫方法去實現。
太難理解?
說簡單點:一類事物(動物)有多種形態(貓,狗,豬等)。
02 有什麼用?
增加了程式的靈活性和擴充套件性,不論物件怎麼變,呼叫方式不變。
太難理解?
那先了解下Python的多型實現,再來理解。
首先,Python 的多型是基於鴨子型別實現。
什麼是鴨子型別?
如果一種動物只要行為有相似性,那麼我們就可以認為是鴨子。
比如:鴨子會走路和游泳,是鴨子;人也會走路和游泳,也是“鴨子”
class duck():
def walk(self):
print('I walk, i am a duck')
def swim(self):
print('i swim,i am a duck')
class person():
def walk(self):
print('i walk like a duck')
def swim(self):
print('i swim like a duck')
def watch_duck(a):
a.walk()
a.swim()
small_duck = duck()
watch_duck(small_duck)
# I walk, i am a duck
# i swim,i am a duck
duck_like_man = person()
watch_duck(duck_like_man)
# i walk like a duck
# i swim like a duck
watch_duck接收這個類的物件,但並沒有檢查物件的型別,便直接呼叫物件的walk和swim方法。
多型的靈活性和擴充套件性,便在於它關注的是呼叫物件如何被使用,而並不關注物件本身是什麼。
即,我只關心你是否會走路和游泳,而不關心你究竟是誰。
說回靈活性和擴充性。當你再想增加一個類,比如狗,它也會走路和游泳 。
你只需要增加一個Dog類就可以了。
class Dog():
def walk(self):
print('i walk like a duck')
def swim(self):
print('i swim like a duck')
繼承
01 繼承和過載
什麼是繼承?
動物需要吃和喝,貓繼承自動物,則貓會吃和喝。
什麼是過載?
動物需要吃和喝,貓繼承自動物,則貓會吃和喝,但是貓喝水是用舔的,因此需要特殊處理(過載)一下。
class Animal:
def eat(self):
print("animal eat")
def drink(self):
print("animal drink")
class Cat(Animal):
def drink(self):
print("cat drink by lick")
cat = Cat()
cat.eat()
cat.drink()
02 多繼承
什麼是多繼承?
小花是一個大學生(繼承自學生),在校期間,她兼職做家教(繼承自老師),於是,小花有兩個能力(學習和教書)。
繼承順序(MRO查詢)
Python支援多繼承,但是有繼承順序:
菱形繼承【類似廣度優先查詢】
class D:
def get(self):
print("I'm D")
class B(D):
pass
class C(D):
def get(self):
print("I'm C")
class A(B, C):
pass
a = A()
a.get()
# I'm C
樹型繼承【類似深度優先查詢】
class O:
def get(self):
print("I'm O")
class P:
def get(self):
print("I'm P")
class Z(O):
pass
class Y(P):
pass
class X(Z, Y):
pass
x = X()
x.get()
# I'm O
Python用C3演算法處理多繼承問題,我們可以用 _mro_ 來檢視繼承順序。
print(A.__mro__)
# (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>)
print(X.__mro__)
# (<class '__main__.X'>, <class '__main__.Z'>, <class '__main__.O'>, <class '__main__.Y'>, <class '__main__.P'>, <class 'object'>)
一如既往,做個總結
01 封裝可以理解為保護隱私;
02 多型的關鍵是鴨子型別,明白了鴨子型別,理解多型不再困難;
03 繼承可用,但多繼承需要慎用,如果你非用不可,那必須得研究清楚繼承的層次結構;
04 以上三點,是物件導向的核心,也是你日後工作中,會經常用到的,so,它們很重要。