簡體   English   中英

Python 運行時類型檢查傳遞給裝飾器的函數是否具有正確的簽名

[英]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_inspecttypeguard包,但找不到我需要的功能。

我正在使用 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM