網站首頁 編程語言 正文
python實現泛型函數
泛型,即“參數化類型”。一提到參數,最熟悉的就是定義方法時有形參,然后調用此方法時傳遞實參。那么參數化類型怎么理解呢?顧名思義,就是將類型由原來的具體的類型參數化,類似于方法中的變量參數,此時類型也定義成參數形式(可以稱之為類型形參),然后在使用/調用時傳入具體的類型。 ——來自百度
簡易理解
泛型函數就是你定義函數的時候, 能接收萬能類型, 在調用時, 會根據傳入值本身的類型進行區分處理, 達到某些效果, 好處是代碼復用率高, 減少代碼冗余, 對面向對象語言中泛型函數概念非常常用.
接下來使用到的py庫 functools 中的 singledispatch 模塊
使用方法
在需要進行泛型的函數上加上裝飾器即可
from functools import singledispatch
@singledispatch
def add(obj):
? ? return obj
- 1 singledispatch : 標記處理函數傳值類型
- 2 register(類型): 為傳值判斷類型后輸出結果
- 3 后續使用無需寫函數名, 只要有register(類型裝飾器)即可調用
- 4 定義需要判斷的類型int str tuple dict list set 根據自己需求
函數中實現類型判斷
from functools import singledispatch
@singledispatch
def add(obj):
? ? return obj
int類型
@add.register(int)
def _(add):
? ? print("int類型")
@add.register(str)
def _(add):
? ? print("str類型")
? ??
@add.register(list)
def _(add):
? ? print("list類型")
? ??
@add.register(tuple)
def _(add):
? ? print("tuple類型")
? ??
@add.register(dict)
def _(add):
? ? print("dict類型")
? ??
@add.register(set)
def _(add):
? ? print("set類型")
? ??
add([1,2,3]) ?
輸出結果: list類型
根據輸入的內容進行判斷類型輸出
對象中使用
from functools import singledispatch
class Type:
? ? @singledispatch
? ? def add(obj):
? ? ? ? return obj
? ? @add.register(int)
? ? def _(add):
? ? ? ? print("int類型")
? ? @add.register(str)
? ? def _(add):
? ? ? ? print("str")
? ? @add.register(list)
? ? def _(add):
? ? ? ? print("list類型")
? ? @add.register(tuple)
? ? def _(add):
? ? ? ? print("tuple類型")
? ? @add.register(dict)
? ? def _(add):
? ? ? ? print("dict類型")
? ? @add.register(set)
? ? def _(add):
? ? ? ? print("set類型")
Type.add([1,2,3])
輸出結果:list類型
不調用singledispatch模塊實現泛型函數
這里需要實現一個類型拼接操作, 如下代碼
在此之前需要先定義一個裝飾器, 來判斷兩個類型是否相同, 如果不同則不作后續判斷, 節省資源消耗
def check_type(func):
? ? def wrapper(*args, **kwargs):
? ? ? ? args1, args2 = args[:2]
? ? ? ? if type(args1) != type(args2):
? ? ? ? ? ? return "兩種類型不一致, 不能做拼接"
? ? ? ? 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]))
結果與上方一樣, 按需選擇
例子很簡單, 最后多用于tcp/ip接收判斷使用
提示: bool類型也是可以的,完!
Python泛型思考
近日在學習Python內容時學習到了泛型,但從個人看法來說Python泛型與Java的泛型有很大的不同,在此提出一點個人的看法
首先,針對Java的泛型,其主要作用是作為某些以后才指定類型的替代,在編寫過程中這些泛型可以在實例化過程中由參數指定,典型例子如集合類當中的泛型
List<String> list = new ArrayList<String>()
這就相當于指定了該集合類的新類型。泛型使用的原因是可以加強類型轉化的安全性以及減少轉換的次數。比如在上例中的List集合中,如果從中取出一個元素,在未指明泛型的前提下,取出的類型元素只能是Object,必須使用強制類型轉換轉化為對應的類型才能供后續代碼使用。
那么,此處就可能存在問題,因為沒有指明泛型,那么意味著加入集合的時候只要你的元素類型是Object即可加入,由于在Java中Object為最高基類,意味著任何元素都可加入泛型當中,由此,沒有任何辦法保證你取出的元素一定是你想要的的類型,所以此時為保證程序健壯性必須處理ClassCastException異常;但在指明泛型后,由于出入都可以限制元素類型,所以減少了此種轉換的異常,也就保證了轉換的安全性。
由以上描述可以知道,泛型首先要求的是你能夠在實例化時指定類型,所以泛型一般應用于強類型的語言當中才比較好用,但Python本身是弱類型語言,所以Python的泛型并不完全是這種作用
Python的泛型類Generic的注釋中提到,
A generic type is typically declared by inheriting from an instantiation of this class with one or more type variables.
也就是說,Python 的泛型類型是繼承這個類之后才會聲明,這種聲明方式與Python的抽象類聲明方式十分類似。以IO下的三個實現類為例,其聲明分別為
class IO(Generic[AnyStr]):
class BinaryIO(IO[bytes]):
class TextIO(IO[str]):
從這些定義中可以看出,在聲明泛型類之后IO類便可以使用泛型的方式去作為其他類的基類定義,
并且AnyStr在Python的類型聲明中是包含了bytes與str兩類的,由此我們可以發現Python的泛型與Java泛型的一個最根本區別:Python 的泛型是在聲明時就指定了泛型類型,也就是說,Python的泛型類型主要作用是:某個類存在多種使用場景,并且我們可以預知各個使用場景的類型,為了將原始代碼能夠廣泛應用于其他場景上使用泛型去保障代碼在各個場景上的通用性。因此,在泛型類的聲明中并不像其他語言一樣使用類似T的方式去替代類型,而是直接使用已經聲明的泛型類型在代碼中書寫,如readline函數的定義
? ? @abstractmethod
? ? def readline(self, limit: int = -1) -> AnyStr:
? ? ? ? pass
由此,我們可以歸納Python泛型的兩個條件:
1.繼承Generic類,并在類的參數中指明泛型類型
2.在實現中使用泛型類型參與代碼編寫
最后,由于在聲明時就已經指定了泛型的類型,所以Python泛型更大程序上我認為是一個具有輔助說明的功能,相當于說明在編寫當中告訴編程人員應當使用什么類型,這其實從另一個層面上也是在其他語言中泛型功能的一大體現?
原文鏈接:https://blog.csdn.net/weixin_45591980/article/details/110140323
相關推薦
- 2022-03-20 Android自動攔截與接聽功能APK黑白名單_Android
- 2022-09-13 c++如何實現歸并兩個有序鏈表_C 語言
- 2021-12-10 Oracle數據庫備份還原詳解_oracle
- 2022-04-22 golang數據類型【字符類型】以及fmt的輸出輸入、UTF-8 和 Unicode 有何區別?
- 2022-07-07 Python數據分析Matplotlib?柱狀圖繪制_python
- 2022-10-25 Go語言實戰學習之流程控制詳解_Golang
- 2022-12-01 C++中高性能內存池的實現詳解_C 語言
- 2022-08-23 Redis?ziplist?壓縮列表的源碼解析_Redis
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支