python 函数如何指定参数类型?

  • Post category:Python

在Python中,我们可以使用函数注解(function annotation)来指定函数参数的类型。函数注解是在函数定义的参数列表后面使用冒号“:”分隔的表达式。例如,下面这个函数使用了函数注解来指定参数a和b的类型为整数:

def add(a: int, b: int) -> int:
    return a + b

在上面的代码中,我们使用“->”符号来指定函数返回值的类型为整数。现在让我们更详细地了解如何使用函数注解来指定函数参数类型的完整攻略。

  1. 定义函数时,在参数列表后面加上注解

在函数定义时,你可以在参数列表后面加上注解来指定参数的类型,例如:

def func(a: int, b: str, c: float) -> bool:
    # function body

在上面的代码中,我们定义了一个名为“func”的函数,其中包含三个参数:a,b和c。使用冒号“:”与参数类型进行注解,例如“a: int”,表示参数a应该是一个整数类型。

需要注意的是,函数注解只是对参数和返回值的提示,并不会对函数执行过程中的参数类型进行检查,也不会对代码的执行性能产生影响。

  1. 对函数注解进行解释

在注解中,不仅可以使用简单的数据类型,还可以使用列表、元组、自定义函数等。例如:

from typing import List, Tuple

def func(a: int, b: str, c: List[int], d: Tuple[str, float]) -> bool:
    # function body

在上面的代码中,我们使用了Python中内置的“typing”模块来定义参数a、b、c和d的类型。其中,参数c是一个整数类型的数组,参数d是一个由字符串和浮点数组成的元组。

  1. 调用函数时,可以传入任何类型的对象

函数注解并不会限制传递给函数的参数类型。你可以传入任何类型的对象,包括不符合注解类型的对象,例如:

func(1, "hello", [1, 2, 3], ("a", 1.5))
func("abc", 123, [1, 2, 3], ("a", 1.5))

在上面的示例中,我们传递了不同类型的参数给函数“func”,包括整数、字符串、数组和元组。

  1. 字符串,列表和字典的注释

在函数注释中,如果你想指定字符串、列表或字典的类型,那么需要使用特殊的语法。例如:

def func(a: str, b: List[int], c: dict[str, float]) -> None:
    # function body

在上面的代码中,参数b是一个由整数类型组成的列表,参数c是一个由字符串类型作为键名、浮点数类型作为键值的字典。

  1. 函数的返回值注释

除了函数参数外,你还可以使用函数注释来指定函数返回值的类型。例如:

def add(a: int, b: int) -> int:
    return a + b

在上面的代码中,我们使用“->”符号来指定函数“add”的返回值类型为整数类型。

  1. 使用类型提示进行参数验证

虽然注释不会对函数执行过程中的参数类型进行检查,但你仍然可以使用类型提示(type hinting)来验证函数参数的类型。例如:

def func(a: int, b: str, c: List[int]) -> bool:
    if not isinstance(a, int):
        raise TypeError("a must be an integer")
    if not isinstance(b, str):
        raise TypeError("b must be a string")
    if not isinstance(c, list) or not all(isinstance(x, int) for x in c):
        raise TypeError("c must be a list of integers")
    return True

在上面的代码中,我们对参数a、b和c的类型进行了验证,并且在参数类型不正确的情况下抛出类型错误的异常。

  1. 使用第三方库进行参数验证

如果你觉得手动验证函数参数类型比较麻烦,你可以使用第三方库来进行自动验证。例如,下面是使用第三方库“decorator”进行参数验证的示例代码:

from decorator import decorator
from typing import List

@decorator
def validate(func, *args, **kwargs):
    annotations = func.__annotations__
    for index, arg in enumerate(args):
        if isinstance(arg, list) and annotations.get(f"_{index}_var", None) == List[int]:
            if not all(isinstance(x, int) for x in arg):
                raise TypeError(f"Argument {index+1} must be a List of integers")
    for key, value in kwargs.items():
        if isinstance(value, list) and annotations.get(key, None) == List[int]:
            if not all(isinstance(x, int) for x in value):
                raise TypeError(f"Argument '{key}' must be a List of integers")
    return func(*args, **kwargs)

@validate
def func(a: int, b: List[int], c: str) -> None:
    # function body

在上面的代码中,我们使用了第三方库“decorator”来定义了一个名为“validate”的装饰器,它可以验证函数的参数类型是否正确。在这个装饰器中,我们首先获取了函数的注释,然后对传递给函数的参数类型进行验证。

总之,使用函数注解来指定参数类型可以提高代码的可读性,并且可以在文档中方便地描述函数参数的具体要求。同时,你也可以自行验证参数类型或使用第三方库进行参数验证,保证函数的正确使用。