Python 装饰器类型提示

问题描述 投票:0回答:1

考虑以下代码:

from functools import wraps
from netmiko import ConnectHandler

class my_class():

    def __init__(self):
        self.connection = ConnectHandler()

    def validate_connection():
        @wraps(func)
        def inner(self, *args, **kwargs):
            if self.connection is None:
                raise Exception(
                    f"No connection to {self.name}({self.ip}):22\n"
                )
            return func(self, *args, **kwargs)

        return inner


    @validate_connection
    def send_command(self, *args, **kwargs) -> Union[str, list[Any], dict[str, Any]]:
        return self.connection.send_command(*args, **kwargs, read_timeout=60)

输入提示

validate_connection()
方法的正确方法是什么,请解释一下你是如何想到的。

目前 MyPy 在

@validate_connection
行上给出以下错误

Argument 1 to "validate_connection" has incompatible type "Callable[[my_class, VarArg(Any), KwArg(Any)], str | list[Any] | dict[str, Any]]"; expected "my_class"
python mypy python-decorators type-hinting
1个回答
0
投票

我会将装饰器拉出到顶级函数中,然后向

self
添加显式类型提示。然后你可以为函数参数创建一个类型变量。此示例中有一个强制转换,并假设它将始终在特定类上使用,但大大简化了类型提示。

from functools import wraps
from typing import Any, TypeVar, Callable, cast, List

Func = TypeVar("Func", bound=Callable[..., Any])


def validate_connection(func: Func) -> Func:
    @wraps(func)
    def inner(self: "MyClass", *args: Any, **kwargs: Any) -> Any:
        if self.connection is None:
            raise Exception
        return func(self, *args, **kwargs)

    return cast(Func, inner)


class MyClass:
    def __init__(self) -> None:
        self.connection = None

    @validate_connection
    def send_command(self, foo: int, bar: str) -> List[str]:
        return []

mypy 输出证明验证的示例:

MyClass().send_command(1, "2").append("3")
# No error :)

MyClass().send_command(1, "2").append(3)
# error: Argument 1 to "append" of "list" has incompatible type "int"; expected "str"  [arg-type]

MyClass().send_command(1, 2).append("3")
# error: Argument 2 to "send_command" of "MyClass" has incompatible type "int"; expected "str"  [arg-type]
© www.soinside.com 2019 - 2024. All rights reserved.