day21 物件導向高階

2022-07-07 17:42:10 字數 4954 閱讀 8862

多型指的是一類事物有多種形態,比如動物有多種形態:貓、狗、豬

class animal: #同一類事物:動物

def talk(self):

pass

class cat(animal): #動物的形態之一:貓

def talk(self):

print('喵喵喵')

class dog(animal): #動物的形態之二:狗

def talk(self):

print('汪汪汪')

class pig(animal): #動物的形態之三:豬

def talk(self):

print('哼哼哼')

#例項化得到三個物件

>>> cat=cat()

>>> dog=dog()

>>> pig=pig()

多型性指的是可以在不用考慮物件具體型別的情況下而直接使用物件,這就需要在設計時,把物件的使用方法統一成一種:例如cat、dog、pig都是動物,但凡是動物肯定有talk方法,於是我們可以不用考慮它們三者的具體是什麼型別的動物,而直接使用

>>> cat.talk()

喵喵喵》 dog.talk()

汪汪汪》 pig.talk()

哼哼哼

更進一步,我們可以定義乙個統一的介面來使用

>>> def talk(animal):

... animal.talk()

...

>>> talk(cat)

喵喵喵》 talk(dog)

汪汪汪》 talk(pig)

哼哼哼

python中一切皆物件,本身就支援多型性

# 我們可以在不考慮三者型別的情況下直接使用統計三個物件的長度

s.__len__()

l.__len__()

t.__len__()

# python內建了乙個統一的介面

len(s)

len(l)

len(t)

多型性的好處在於增強了程式的靈活性和可擴充套件性,比如通過繼承animal類建立了乙個新的類,例項化得到的物件obj,可以使用相同的方式使用obj.talk()

>>">...     def talk(self):

... print('嗷...')

...

>>> wolf=wolf() # 例項出一頭狼

>>> wolf.talk() # 使用者根本無需關心wolf是什麼型別而呼叫talk

嗷...

綜上我們得知,多型性的本質在於不同的類中定義有相同的方法名,這樣我們就可以不考慮類而統一用一種方式去使用物件,可以通過在父類引入抽象類的概念來硬性限制子類必須有某些方法名

import abc

# 指定metaclass屬性將類設定為抽象類,抽象類本身只是用來約束子類的,不能被例項化

class animal(metaclass=abc.abcmeta):

@abc.abstractmethod # 該裝飾器限制子類必須定義有乙個名為talk的方法

def talk(self): # 抽象方法中無需實現具體的功能

pass

class cat(animal): # 但凡繼承animal的子類都必須遵循animal規定的標準

def talk(self):

pass

cat=cat() # 若子類中沒有乙個名為talk的方法則會丟擲異常typeerror,無法例項化

但其實我們完全可以不依賴於繼承,只需要製造出外觀和行為相同物件,同樣可以實現不考慮物件型別而使用物件,這正是python崇尚的「鴨子型別」(duck typing):「如果看起來像、叫聲像而且走起路來像鴨子,那麼它就是鴨子」。比起繼承的方式,鴨子型別在某種程度上實現了程式的松耦合度,如下

#二者看起來都像檔案,因而就可以當檔案一樣去用,然而它們並沒有直接的關係

class txt: #txt類有兩個與檔案型別同名的方法,即read和write

def read(self):

pass

def write(self):

pass

class disk: #disk類也有兩個與檔案型別同名的方法:read和write

def read(self):

pass

def write(self):

pass

python是動態語言,而反射(reflection)機制被視為動態語言的關鍵。

反射機制指的是在程式的執行狀態中

對於任意乙個類,都可以知道這個類的所有屬性和方法;

對於任意乙個物件,都能夠呼叫他的任意方法和屬性。

這種動態獲取程式資訊以及動態呼叫物件的功能稱為反射機制。

在python中實現反射非常簡單,在程式執行過程中,如果我們獲取乙個不知道存有何種屬性的物件,若想操作其內部屬性,可以先通過內建函式dir來獲取任意乙個類或者物件的屬性列表,列表中全為字串格式

>>> class people:

... def __init__(self,name,age,gender):

... self.name=name

... self.age=age

... self.gender=gender

...

>>> obj=people('egon',18,'male')

>>> dir(obj) # 列表中檢視到的屬性全為字串

[......,'age', 'gender', 'name']

接下來就是想辦法通過字串來操作物件的屬性了,這就涉及到內建函式hasattr、getattr、setattr、delattr的使用了(python中一切皆物件,類和物件都可以被這四個函式操作,用法一樣)

class teacher:

def __init__(self,full_name):

self.full_name =full_name

t=teacher('egon lin')

# hasattr(object,'name')

hasattr(t,'full_name') # 按字串'full_name'判斷有無屬性t.full_name

# getattr(object, 'name', default=none)

getattr(t,'full_name',none) # 等同於t.full_name,不存在該屬性則返回預設值none

# setattr(x, 'y', v)

setattr(t,'age',18) # 等同於t.age=18

# delattr(x, 'y')

delattr(t,'age') # 等同於del t.age

基於反射可以十分靈活地操作物件的屬性,比如將使用者互動的結果反射到具體的功能執行

>>> class ftpserver:

... def serve_forever(self):

... while true:

... inp=input('input your cmd>>: ').strip()

... cmd,file=inp.split()

... if hasattr(self,cmd): # 根據使用者輸入的cmd,判斷物件self有無對應的方法屬性

... func=getattr(self,cmd) # 根據字串cmd,獲取物件self對應的方法屬性

... func(file)

... def get(self,file):

... print('downloading %s...' %file)

... def put(self,file):

... print('uploading %s...' %file)

...

>>> server=ftpserver()

>>> server.serve_forever()

input your cmd>>: get a.txt

downloading a.txt...

input your cmd>>: put a.txt

uploading a.txt...

定義在類內部,以__開頭並以__結束的方法

特點:會在某種情況下自動觸發執行

為了定製化我們的類或物件

class people:

def __init__(self,name,age):

self.name = name

self.age = age

def __str__(self):

return "<%s:%s>" %(self.name,self.age)

obj = people("egon",19)

print(obj) # print(obj.__str__())

class people:

def __init__(self,name,age):

self.name = name

self.age = age

self.f = open('a.txt',mode='rt',encoding='utf-8')

def __del__(self):

self.f.close()

obj = people("egon",19)

# del obj

print('**********===end***************====')

day21物件導向 類

1 1 定義階段 2class harvordstudent 3 school harvord 4 defchoose course self 5print hello 6print harvordstudent 類的本質是命名空間 容器,可以增刪改查名字7 訪問屬性 命名空間中名字 的語法,之後的...

day44 5 物件導向高階

class car pass class foo def new cls,args,kwargs obj car return obj def init self,name self.name name print 我是init f foo lqz print f.name class foo de...

day21 物件導向之繼承和組合

繼承 組合oop的三大特徵之一 封裝,繼承,多型 繼承什麼是繼承?繼承是一種關係,描述兩個物件之間,什麼是什麼的關係 例如 麥兜,佩奇,豬剛鬣 都是豬啊,在程式中,繼承描述的是類和類之間的關係 例如 a繼承了b,a就能直接使用b已經存在的方法和屬性,a稱之為子類,b稱之為父類,也稱之為基類 為什麼要...