面向對象之多態,多態性,反射,以及基於反射的可拔插設計
阿新 • • 發佈:2018-04-10
it is sat pass ict method func let HA strac
多態
什麽多態?
多態指的是一類事物有多種形態,比如
動物有多種形態:人,狗,豬
>>例如
import abc #創建抽象類 導入abc class Animal(metaclass=abc.ABCMeta): #同一類事物:動物 @abc.abstractmethod #歸一化設計 def talk(self): pass class People(Animal): #動物的形態之一:人 def talk(self): print('say hello') class Dog(Animal): #動物的形態之二:狗 def talk(self): print('say wangwang') class Pig(Animal): #動物的形態之三:豬 def talk(self): print('say aoao') 文件也有多態性比如: 文件有多種形態:文本文件,可執行文件 import abc class File(metaclass=abc.ABCMeta): #同一類事物:文件 @abc.abstractmethod def click(self): pass class Text(File): #文件的形態之一:文本文件 def click(self): print('open file') class ExeFile(File): #文件的形態之二:可執行文件 def click(self): print('execute file')
多態性
1.什麽是多態性
多態性是指在不考慮實例類型的情況下使用實例,多態性分為 靜態多態性 和 動態多態性
靜態多態性:如任何類型都可以用運算符+進行運算
動態多態性如下實例:
peo=People()
dog=Dog()
pig=Pig()
#peo、dog、pig都是動物,只要是動物肯定有talk方法
#於是我們可以不用考慮它們三者的具體是什麽類型,而直接使用
peo.talk()
dog.talk()
pig.talk()
#更進一步,我們可以定義一個統一的接口來使用,動態的執行不同動物的talk方法
def func(obj):
obj.talk()
二 為什麽要用多態性(多態性的好處)
1.增加了程序的靈活性>>>
以不變應萬變,不論對象千變萬化,使用者都是同一種形式去調用,如func(animal)
2.增加了程序額可擴展性>>>
通過繼承animal類創建了一個新的類,使用者無需更改自己的代碼,還是用func(animal)去調用
class H2O: #水有多種形態冰,液態水,水蒸氣
def init(self, name, temp):
self.name = name
self.temp = temp
def turn_active(self): if self.temp < 0: print("我是 %s 我已經變成冰了!" % self.name) elif self.temp > 0 and self.temp < 100: print("我是液水") elif self.temp > 100: print("我是%s 我變成水蒸氣了" % self.name) class Water(H2O): pass class Iire(H2O): pass class Vapor(H2O): pass w1 = Water('水', 10) #生成各自的實例 i1 = Iire("冰", -100) v1 = Vapor("水蒸氣", 1000) # ************ def func(obj): ##對於使用者來說,自己的代碼根本無需改動 obj.turn_active() func(w1) #實例調用統一的接口來實行trun_active()方法
二 反射
1.什麽反射:
反射的概念是由Smith在1982年首次提出的,主要是指程序可以訪問、檢測和修改它本身狀態或行為的一種能力(自省)。這一概念的提出很快引發了計算機科學領域關於應用反射性的研究。它首先被程序語言的設計領域所采用,並在Lisp和面向對象方面取得了成績。
2.python面向對象中的反射:
通過字符串的形式操作對象相關的屬性。python中的一切事物都是對象(都可以使用反射)
四個可以實現自省的函數 下列方法適用於類和對象(一切皆對象,類本身也是一個對象)[hasattr,getattr,setattr,delattr]
hasattr(object,name)
判斷object中有沒有一個name字符串對應的方法或屬性
getattr(object, name, default=None)
獲取對象的屬性方法(Get a named attribute from an object)
def getattr(object, name, default=None): # known special case of getattr
"""
getattr(object, name[, default]) -> value
Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
When a default argument is given, it is returned when the attribute doesn't
exist; without it, an exception is raised in that case.
"""
pass
setattr(x, y, v)
def setattr(x, y, v): # real signature unknown; restored from __doc__
"""
Sets the named attribute on the given object to the specified value.
setattr(x, 'y', v) is equivalent to ``x.y = v''
"""
pass
delattr(x, y)
def delattr(x, y): # real signature unknown; restored from __doc__
"""
Deletes the named attribute from the given object.
delattr(x, 'y') is equivalent to ``del x.y''
"""
pass
四個方法的使用演示
class BlackMedium:
feture = 'Ugly'
def __init__(self, name, addr):
self.name = name
self.addr = addr
def sell_hourse(self):
print('【%s】 正在賣房子,傻逼才買呢' % self.name)
def rent_hourse(self):
print('【%s】 正在租房子,傻逼才租呢' % self.name)
b1=BlackMedium("黑中介","北京")
print(hasattr(b1,"name")) #判斷實例有沒有name的這個屬性
func=getattr(b1,"sell_hourse")# 獲得實例屬性
func()
func1=getattr(b1,"sell_hoursedasd","沒有這個屬性") # default默認值
print(func1)
setattr(b1,"key","v1") #給對應實例添加數據屬性
print(b1.__dict__)
delattr(b1,"key") # 刪除實例的屬性
print(b1.__dict__)
setattr(b1,"func2",lambda x:x+1) #實例 設置 函數屬性
print(b1.func2(10))
三、動態導入模塊
mm為當前目錄下的文件夾下面有tt.py
m = model_t = __import__("mm.tt") # 只能導入第一層
print(m)
m.tt.test1()
import importlib #使用模塊 動態導入,推薦這種方法
m2=importlib.import_module("mm.tt")
print(m2)
m2.test2()
四、基於反射實現可拔插組件
bob正在負責寫FTP的客戶端,但是最近他有大事,給耽誤了,並且其他人需要用到這個ftp中的一些方法,這時候我們就需要用到反射
客戶端殘次品代碼
class FtpClient:
def __init__(self,name):
print("client ....")
self.name=name
調用者需要基於反射調用FTp的客戶端,如下:
from Ftp_client import *
c1 = FtpClient("client")
if hasattr(c1, "put"): #判斷FTP客戶端有沒有put方法
put_func = getattr(c1, "put") # 有就調用執行
put_func()
else:
print("沒有執行put 完成其他操作!") #沒有do other things!
面向對象之多態,多態性,反射,以及基於反射的可拔插設計