python極簡教程07:封裝、多型和繼承

測試奇譚發表於2022-01-17

測試奇譚,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,它們很重要。

相關文章