[英]Python runtime type check that function passed to a decorator has correct signature
我有一個 python 裝飾器,它期望傳遞函數的簽名是一個User
和一個Point
,它返回一個具有相同簽名的函數:
@dataclass
class User:
name: str
@dataclass
class Point:
x: float
y: float
z: float
def logging_decorator(f: Callable[[User, Point], bool]) -> Callable[[User, Point], bool]:
print('decorating function...')
def decorated(a: User, b: Point) -> bool:
print(f'User {a.name} calling with points {b.x},{b.y},{b.z}')
ret = f(a, b)
print(f'returned {ret}')
return ret
return decorated
在它打印decorating function...
,我希望它檢查傳入的函數是否具有正確的簽名,如果沒有,則給出合理的錯誤消息。
下面是一個裝飾兩個函數的例子,一個有正確的簽名,一個有不正確的簽名:
@logging_decorator
def good_f(a: User, b: Point) -> bool:
return True
@logging_decorator
def bad_f(a: str, b: str) -> str:
return "Hello"
如何向logging_decorator
添加檢查,以便檢查被裝飾的函數是否具有正確的參數類型?
我曾嘗試使用typing_inspect
和typeguard
包,但找不到我需要的功能。
我正在使用 Python 3.8.3
使用標准庫中的inspect
模塊。 使用inspect.signature
,您可以編寫如下函數驗證代碼:
import inspect
def validate_func(func):
def good_func(a: User, b: Point) -> bool: ...
good_func_signature = inspect.signature(good_func)
received_signature = inspect.signature(func)
if received_signature != good_func_signature:
raise TypeError(
f'Invalid function signature: '
f'expected "{good_func_signature}", '
f'got "{received_signature}"'
)
(您可以將此邏輯放在您的用例的裝飾器中;我只是將它作為一個單獨的函數編寫,以使其與您的代碼分開。)
使用中:
>>> validate_func(good_f)
>>> validate_func(lambda a, b: a)
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "<string>", line 6, in validate_func
TypeError: Invalid function signature: expected "(a:__main__.User, b:__main__.Point) -> bool", got "(a, b)"
>>> validate_func(bad_f)
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "<string>", line 6, in validate_func
TypeError: Invalid function signature: expected "(a:__main__.User, b:__main__.Point) -> bool", got "(a:str, b:str) -> str"
如果您願意,您可以在簽名之間進行更詳細和細粒度的比較,而不僅僅是簡單的相等性檢查。 可以通過inspect.signature
的返回值比較參數個數、參數名稱、參數種類(positional-only/positional-or-keyword/keyword-only)、參數是否有注解,參數的注解是什么,參數是否有默認值。 您可以在此處找到inspect.signature
的文檔。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.