日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Python中的函數參數類型檢查_python

作者:子休_ ? 更新時間: 2023-01-18 編程語言

Python函數參數類型檢查

有一個很經典的笑話:

三個月之前,只有我和上帝知道這代碼是干什么的。

現在,只有上帝知道了。

在Python中,不知道函數參數類型是一個很正常的事情,特別是在一個大項目里。

我見過有些項目里,每一個函數體的前十幾行都在檢查參數類型,這實在是太麻煩了。而且一旦參數有改動,這部分也需要改動。

下面我們用裝飾器來實現

函數參數的強制類型檢查。

首先,這個裝飾器,要接受類型參數,和指定函數參數的類型參數。也就是一個list和一個dict

from functools import wraps

def typeassert(*type_args, **type_kwargs):
? ? def decorate(func):
? ? ? ? @wraps(func)
? ? ? ? def wrapper(*args, **kwargs):
? ? ? ? ? ? return func(*args, **kwargs)
? ? ? ? return wrapper
? ? return decorate

@wraps(func)的作用請看我的另一篇

那么,接下來,在裝飾器中,我們需要獲取函數參數列表,并且要和類型參數表映射。

這要借助Python的一個標準庫——inspect 這個庫一般用于Python代碼調試

from inspect import signature
from functools import wraps

def typeassert(*type_args, **type_kwargs):
? ? def decorate(func):
? ? ? ? sig = signature(func)
? ? ? ? bound_types = sig.bind_partial(*type_args, **type_kwargs).arguments

? ? ? ? @wraps(func)
? ? ? ? def wrapper(*args, **kwargs):
? ? ? ? ? ? return func(*args, **kwargs)
? ? ? ? return wrapper
? ? return decorate

上面的代碼中,我們使用inspect中的signature方法獲取了func的Signature對象,然后使用bind_partial方法創建了(*type_args, **type_kwargs)到func參數的映射(也就是一個字典)。

接下來就簡單了,我們只需要再獲取(*args, **kwargs)的類型,使用isintance函數進行比較就好。

from inspect import signature
from functools import wraps

def typeassert(*type_args, **type_kwargs):
? ? def decorate(func):
? ? ? ? sig = signature(func)
? ? ? ? bound_types = sig.bind_partial(*type_args, **type_kwargs).arguments

? ? ? ? @wraps(func)
? ? ? ? def wrapper(*args, **kwargs):
? ? ? ? ? ? bound_values = sig.bind(*args, **kwargs)
? ? ? ? ? ? for name, value in bound_values.arguments.items():
? ? ? ? ? ? ? ? if name in bound_types:
? ? ? ? ? ? ? ? ? ? if not isinstance(value, bound_types[name]):
? ? ? ? ? ? ? ? ? ? ? ? raise TypeError('Argument {} must be {}'.format(name, bound_types[name]))
? ? ? ? ? ? return func(*args, **kwargs)
? ? ? ? return wrapper
? ? return decorate

運行如下代碼

@typeassert(int, int)
def add(x, y):
? ? return x+y

print(add("u", 2))

能看到報錯如下

Traceback (most recent call last):
? File "c:\Users\Chen\Desktop\typeassert.py", line 32, in <module>
? ? print(add("u", 2))
? File "c:\Users\Chen\Desktop\typeassert.py", line 22, in wrapper
? ? 'Argument {} must be {}'.format(name, bound_types[name])
TypeError: Argument x must be <class 'int'>

很貼心的提醒了我們哪一個參數應該是什么類型。

你甚至可以自己改動這個裝飾器,讓它還能告訴你傳進去了什么錯誤參數(特別是寫爬蟲的時候,參數很難掌握,一旦報錯,還得重跑一遍才知道為什么。)

你也可以指定某一個參數的類型,譬如

@typeassert(int, z=str)
def display(x, y, z):
? ? print(x, y, z)

這時你會發現,y的類型就像原生的Python函數一樣,什么都行。而x必須是int,z必須是str。

總結

原文鏈接:https://www.jianshu.com/p/7a2c9133a002

欄目分類
最近更新