使用python如何實(shí)現(xiàn)泛型函數(shù)
python實(shí)現(xiàn)泛型函數(shù)
泛型,即“參數(shù)化類(lèi)型”。一提到參數(shù),最熟悉的就是定義方法時(shí)有形參,然后調(diào)用此方法時(shí)傳遞實(shí)參。那么參數(shù)化類(lèi)型怎么理解呢?顧名思義,就是將類(lèi)型由原來(lái)的具體的類(lèi)型參數(shù)化,類(lèi)似于方法中的變量參數(shù),此時(shí)類(lèi)型也定義成參數(shù)形式(可以稱之為類(lèi)型形參),然后在使用/調(diào)用時(shí)傳入具體的類(lèi)型。 ——來(lái)自百度
簡(jiǎn)易理解
泛型函數(shù)就是你定義函數(shù)的時(shí)候, 能接收萬(wàn)能類(lèi)型, 在調(diào)用時(shí), 會(huì)根據(jù)傳入值本身的類(lèi)型進(jìn)行區(qū)分處理, 達(dá)到某些效果, 好處是代碼復(fù)用率高, 減少代碼冗余, 對(duì)面向?qū)ο笳Z(yǔ)言中泛型函數(shù)概念非常常用.
接下來(lái)使用到的py庫(kù) functools 中的 singledispatch 模塊
使用方法
在需要進(jìn)行泛型的函數(shù)上加上裝飾器即可
from functools import singledispatch @singledispatch def add(obj): ? ? return obj
- 1 singledispatch : 標(biāo)記處理函數(shù)傳值類(lèi)型
- 2 register(類(lèi)型): 為傳值判斷類(lèi)型后輸出結(jié)果
- 3 后續(xù)使用無(wú)需寫(xiě)函數(shù)名, 只要有register(類(lèi)型裝飾器)即可調(diào)用
- 4 定義需要判斷的類(lèi)型int str tuple dict list set 根據(jù)自己需求
函數(shù)中實(shí)現(xiàn)類(lèi)型判斷
from functools import singledispatch
@singledispatch
def add(obj):
? ? return obj
int類(lèi)型
@add.register(int)
def _(add):
? ? print("int類(lèi)型")
@add.register(str)
def _(add):
? ? print("str類(lèi)型")
? ??
@add.register(list)
def _(add):
? ? print("list類(lèi)型")
? ??
@add.register(tuple)
def _(add):
? ? print("tuple類(lèi)型")
? ??
@add.register(dict)
def _(add):
? ? print("dict類(lèi)型")
? ??
@add.register(set)
def _(add):
? ? print("set類(lèi)型")
? ??
add([1,2,3]) ?輸出結(jié)果: list類(lèi)型
根據(jù)輸入的內(nèi)容進(jìn)行判斷類(lèi)型輸出
對(duì)象中使用
from functools import singledispatch
class Type:
? ? @singledispatch
? ? def add(obj):
? ? ? ? return obj
? ? @add.register(int)
? ? def _(add):
? ? ? ? print("int類(lèi)型")
? ? @add.register(str)
? ? def _(add):
? ? ? ? print("str")
? ? @add.register(list)
? ? def _(add):
? ? ? ? print("list類(lèi)型")
? ? @add.register(tuple)
? ? def _(add):
? ? ? ? print("tuple類(lèi)型")
? ? @add.register(dict)
? ? def _(add):
? ? ? ? print("dict類(lèi)型")
? ? @add.register(set)
? ? def _(add):
? ? ? ? print("set類(lèi)型")
Type.add([1,2,3])輸出結(jié)果:list類(lèi)型
不調(diào)用singledispatch模塊實(shí)現(xiàn)泛型函數(shù)
這里需要實(shí)現(xiàn)一個(gè)類(lèi)型拼接操作, 如下代碼
在此之前需要先定義一個(gè)裝飾器, 來(lái)判斷兩個(gè)類(lèi)型是否相同, 如果不同則不作后續(xù)判斷, 節(jié)省資源消耗
def check_type(func): ? ? def wrapper(*args, **kwargs): ? ? ? ? args1, args2 = args[:2] ? ? ? ? if type(args1) != type(args2): ? ? ? ? ? ? return "兩種類(lèi)型不一致, 不能做拼接" ? ? ? ? return func(*args, **kwargs) ? ? return wrapper @check_type def add(obj1, obj2): ? ? if isinstance(obj1,list): ? ? ? ? obj1 += obj2 ? ? ? ? return obj1 ? ? if isinstance(obj1, str): ? ? ? ? obj1 += obj2 ? ? ? ? return obj1 ? ? if isinstance(obj1, tuple): ? ? ? ? obj1 += obj2 ? ? ? ? return obj1 ? ? if isinstance(obj1, dict): ? ? ? ? obj1 += obj2 ? ? ? ? return obj1 print(add([1, 2, 3], [1, 2, 3]))
結(jié)果與上方一樣, 按需選擇
例子很簡(jiǎn)單, 最后多用于tcp/ip接收判斷使用
提示: bool類(lèi)型也是可以的,完!
Python泛型思考
近日在學(xué)習(xí)Python內(nèi)容時(shí)學(xué)習(xí)到了泛型,但從個(gè)人看法來(lái)說(shuō)Python泛型與Java的泛型有很大的不同,在此提出一點(diǎn)個(gè)人的看法
首先,針對(duì)Java的泛型,其主要作用是作為某些以后才指定類(lèi)型的替代,在編寫(xiě)過(guò)程中這些泛型可以在實(shí)例化過(guò)程中由參數(shù)指定,典型例子如集合類(lèi)當(dāng)中的泛型
List<String> list = new ArrayList<String>()
這就相當(dāng)于指定了該集合類(lèi)的新類(lèi)型。泛型使用的原因是可以加強(qiáng)類(lèi)型轉(zhuǎn)化的安全性以及減少轉(zhuǎn)換的次數(shù)。比如在上例中的List集合中,如果從中取出一個(gè)元素,在未指明泛型的前提下,取出的類(lèi)型元素只能是Object,必須使用強(qiáng)制類(lèi)型轉(zhuǎn)換轉(zhuǎn)化為對(duì)應(yīng)的類(lèi)型才能供后續(xù)代碼使用。
那么,此處就可能存在問(wèn)題,因?yàn)闆](méi)有指明泛型,那么意味著加入集合的時(shí)候只要你的元素類(lèi)型是Object即可加入,由于在Java中Object為最高基類(lèi),意味著任何元素都可加入泛型當(dāng)中,由此,沒(méi)有任何辦法保證你取出的元素一定是你想要的的類(lèi)型,所以此時(shí)為保證程序健壯性必須處理ClassCastException異常;但在指明泛型后,由于出入都可以限制元素類(lèi)型,所以減少了此種轉(zhuǎn)換的異常,也就保證了轉(zhuǎn)換的安全性。
由以上描述可以知道,泛型首先要求的是你能夠在實(shí)例化時(shí)指定類(lèi)型,所以泛型一般應(yīng)用于強(qiáng)類(lèi)型的語(yǔ)言當(dāng)中才比較好用,但Python本身是弱類(lèi)型語(yǔ)言,所以Python的泛型并不完全是這種作用
Python的泛型類(lèi)Generic的注釋中提到,
A generic type is typically declared by inheriting from an instantiation of this class with one or more type variables.
也就是說(shuō),Python 的泛型類(lèi)型是繼承這個(gè)類(lèi)之后才會(huì)聲明,這種聲明方式與Python的抽象類(lèi)聲明方式十分類(lèi)似。以IO下的三個(gè)實(shí)現(xiàn)類(lèi)為例,其聲明分別為
class IO(Generic[AnyStr]): class BinaryIO(IO[bytes]): class TextIO(IO[str]):
從這些定義中可以看出,在聲明泛型類(lèi)之后IO類(lèi)便可以使用泛型的方式去作為其他類(lèi)的基類(lèi)定義,
并且AnyStr在Python的類(lèi)型聲明中是包含了bytes與str兩類(lèi)的,由此我們可以發(fā)現(xiàn)Python的泛型與Java泛型的一個(gè)最根本區(qū)別:Python 的泛型是在聲明時(shí)就指定了泛型類(lèi)型,也就是說(shuō),Python的泛型類(lèi)型主要作用是:某個(gè)類(lèi)存在多種使用場(chǎng)景,并且我們可以預(yù)知各個(gè)使用場(chǎng)景的類(lèi)型,為了將原始代碼能夠廣泛應(yīng)用于其他場(chǎng)景上使用泛型去保障代碼在各個(gè)場(chǎng)景上的通用性。因此,在泛型類(lèi)的聲明中并不像其他語(yǔ)言一樣使用類(lèi)似T的方式去替代類(lèi)型,而是直接使用已經(jīng)聲明的泛型類(lèi)型在代碼中書(shū)寫(xiě),如readline函數(shù)的定義
? ? @abstractmethod ? ? def readline(self, limit: int = -1) -> AnyStr: ? ? ? ? pass
由此,我們可以歸納Python泛型的兩個(gè)條件:
1.繼承Generic類(lèi),并在類(lèi)的參數(shù)中指明泛型類(lèi)型
2.在實(shí)現(xiàn)中使用泛型類(lèi)型參與代碼編寫(xiě)
最后,由于在聲明時(shí)就已經(jīng)指定了泛型的類(lèi)型,所以Python泛型更大程序上我認(rèn)為是一個(gè)具有輔助說(shuō)明的功能,相當(dāng)于說(shuō)明在編寫(xiě)當(dāng)中告訴編程人員應(yīng)當(dāng)使用什么類(lèi)型,這其實(shí)從另一個(gè)層面上也是在其他語(yǔ)言中泛型功能的一大體現(xiàn)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python中map,reduce,filter和sorted函數(shù)的使用方法
這篇文章主要介紹了Python中map,reduce,filter和sorted函數(shù)的使用方法,是Python入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-08-08
Python滲透測(cè)試入門(mén)之Scapy庫(kù)的使用詳解
Scapy?是一個(gè)用來(lái)解析底層網(wǎng)絡(luò)數(shù)據(jù)包的Python模塊和交互式程序,該程序?qū)Φ讓影幚磉M(jìn)行了抽象打包,使得對(duì)網(wǎng)絡(luò)數(shù)據(jù)包的處理非常簡(jiǎn)便。本文就來(lái)聊聊它的具體使用,希望對(duì)大家有所幫助2023-03-03
pytorch 網(wǎng)絡(luò)參數(shù) weight bias 初始化詳解
這篇文章主要介紹了pytorch 網(wǎng)絡(luò)參數(shù) weight bias 初始化詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-06-06
Python導(dǎo)入或執(zhí)行python源文件的3種方法
這篇文章主要給大家介紹了關(guān)于Python導(dǎo)入或執(zhí)行python源文件的3種方法,python源代碼的文件以"py"為擴(kuò)展名,由python.exe解釋,可以在控制臺(tái)下運(yùn)行,需要的朋友可以參考下2023-08-08
Python之關(guān)于類(lèi)變量的兩種賦值區(qū)別詳解
這篇文章主要介紹了Python之關(guān)于類(lèi)變量的兩種賦值區(qū)別詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03
Python實(shí)現(xiàn)Socket通信建立TCP反向連接
本文將記錄學(xué)習(xí)基于 Socket 通信機(jī)制建立 TCP 反向連接,借助 Python 腳本實(shí)現(xiàn)主機(jī)遠(yuǎn)程控制的目的。感興趣的可以了解一下2021-08-08
Pycharm配置lua編譯環(huán)境過(guò)程圖解
這篇文章主要介紹了Pycharm配置lua編譯環(huán)境過(guò)程圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11

