leonZhang123

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

day11_函数注解

【一】引言

  • 在Python 3.5版本后引入的typing模块为Python的静态类型注解提供了支持。
  • 这个模块在增强代码可读性和维护性方面提供了帮助。
  • 本文将深入探讨typing模块,介绍其基本概念、常用类型注解以及使用示例,以帮助读者更全面地了解和应用静态类型注解。

【二】基本类型注解

【0】基础语法

# 定义一个函数,参数名和返回值都有类型提示
# 参数类型只是弱约束 ,函数返回值也是弱约束
def process_example(参数名: 参数类型) -> 返回值类型:
    代码块
    return  返回值

【1】内置类型

  • typing模块中提供了与Python内置类型相对应的类型提示,如:
  • int, float, str, bool, bytes, complex

(1)整数类型

# 定义一个名为process_int的函数,接收一个整型参数data,并无返回值(None)
# 函数作用:打印传入数据data的值及其类型
def process_int(data: int) -> None:
    print(f"the data is {data} and the type is {type(data)}")

(2)浮点数类型

# 定义一个名为process_float的函数,接收一个浮点型参数data,并无返回值(None)
# 函数作用:打印传入数据data的值及其类型
def process_float(data: float) -> None:
    print(f"the data is {data} and the type is {type(data)}")

(3)字符串类型

# 定义一个名为process_str的函数,接收一个字符串型参数data,并无返回值(None)
# 函数作用:打印传入数据data的值及其类型
def process_str(data: str) -> None:
    print(f"the data is {data} and the type is {type(data)}")

(4)布尔类型

# 定义一个名为process_bool的函数,接收一个布尔型参数data,并无返回值(None)
# 函数作用:打印传入数据data的值及其类型
def process_bool(data: bool) -> None:
    print(f"the data is {data} and the type is {type(data)}")

【2】类型别名

  • typing模块中有多种内置的类型别名
  • 比如List、Tuple、Dict、Set、Frozenset等,可以用于注解变量和函数的预期类型。

(1)列表类型

# 导入List类型模块以支持类型注解
from typing import List

# 定义一个名为process_numbers的函数,接收一个整数列表(List[int])类型的参数data,并无返回值(None)
# 函数作用:打印传入数据data是一个整数列表,以及列表中的每个元素都是整数类型,同时输出数据本身
def process_numbers(data: List[int]) -> None:
    print(f'this is a number list , the data is {data}  , every item is int and the type is {type(data)}')

(2)字典类型

# 导入Dict类型模块以支持类型注解
from typing import Dict

# 定义一个名为process_dict的函数,接收一个字典(Dict[str, int])类型的参数data,其中键为字符串(str),值为整数(int),并无返回值(None)
# 函数作用:打印传入数据data是一个字典,键为字符串类型,值为整数类型,同时输出数据本身
def process_dict(data: Dict[str, int]) -> None:
    print(f"this is a dict, the data is {data} , the key is str , the value is int")

(3)元组类型

# 导入Tuple类型模块以支持类型注解
from typing import Tuple

# 定义一个名为process_tuple的函数,接收一个元组(Tuple[str])类型的参数data,其中元素为字符串(str),并无返回值(None)
# 函数作用:打印传入数据data是一个元组,所有元素均为字符串类型,同时输出数据本身
def process_tuple(data: Tuple[str]) -> None:
    print(f"this is a tuple, the data is {data} , the item is str")

(4)集合类型

# 导入Set类型模块以支持类型注解
from typing import Set

# 定义一个名为process_set的函数,接收一个集合(Set[int])类型的参数data,其中元素为整数(int),并无返回值(None)
# 函数作用:打印传入数据data是一个集合,所有元素均为整数类型,同时输出数据本身
def process_set(data: Set[int]) -> None:
    print(f"this is a set, the data is {data} , the item is int")

【3】Any

  • 表示任意类型
  • 用于无法确定具体类型或者希望允许任何类型的情况。
# 导入Any类型模块以支持类型注解,Any表示允许任何类型的数据
from typing import Any

# 定义一个名为process_any_data的函数,接收一个Any类型的参数data,表示该参数可以是任何类型的数据
# 函数没有返回值,声明为None
def process_any_data(data: Any) -> None:

    # 使用f-string格式化输出,打印一条信息,内容为:"this is a data can be any type: {data}"
    # 其中"data"处会被实际传入的data变量的值替换
    print(f"this is a data can be any type: {data}")

【4】Union 类型

  • Union允许参数接受多种不同类型的数据。
# 导入Union类型模块以支持类型注解
# Union允许函数接收多种类型作为参数或返回值
from typing import Union

# 定义一个名为double_or_square的函数,接收一个联合类型(Union[int, float])的参数number,可以是整数(int)或浮点数(float)
# 函数返回值也为联合类型(Union[int, float]),即返回结果可能是整数或浮点数
def double_or_square(number: Union[int, float]) -> Union[int, float]:

    # 使用isinstance()函数检查传入的number参数是否为整数类型(int)
    if isinstance(number, int):

        # 如果number是整数,则将其乘以2并返回结果
        return number * 2

    # 否则,认为number为浮点数(else分支对应非int类型,这里假设只能是float)
    else:

        # 将number取平方(计算其二次幂)并返回结果
        return number ** 2

【5】Optional 类型

  • Optional表示参数可以是指定类型或者None。
# 导入Optional类型模块以支持类型注解
# Optional[str]表示字符串类型或None
from typing import Optional

# 定义一个名为greet的函数,接收一个Optional[str]类型的参数name,表示该参数可以是字符串类型或None
# 函数返回一个str类型的结果
def greet(name: Optional[str]) -> str:

    # 如果传入的name参数非空(即存在有效值)
    if name:
        # 使用f-string格式化输出,返回一条问候语,内容为:"Hello, {name}!"
        # 其中{name}处会被实际传入的name变量的值替换
        return f"Hello, {name}!"

    # 否则,当name参数为空(None)时
    else:
        # 返回默认问候语:"Hello, World!"
        return "Hello, World!"

【三】类型变量和泛型

【1】类型变量

  • TypeVar允许创建泛型函数或类。
# 导入TypeVar和List模块,以便使用泛型类型和列表类型进行类型注解
from typing import TypeVar, List

# 定义一个TypeVar对象T,代表一个通用类型,具体类型将在使用时确定
T = TypeVar('T')

# 定义一个名为get_first_element的函数,接收一个List[T]类型的参数items,表示参数是一个包含T类型元素的列表
# 函数返回一个T类型的结果
def get_first_element(items: List[T]) -> T:
    # 返回传入列表items的第一个元素,其类型与列表元素类型一致,即T类型
    return items[0]

# 调用get_first_element函数,传入一个整数列表[1, 2, 3]
# 根据传入列表类型,TypeVar T在此处被推导为int类型
# 函数返回第一个元素,赋值给变量first_element,其类型为int
first_element = get_first_element([1, 2, 3])  # 推导类型为 int

【2】泛型函数

  • Callable和Sequence等泛型类型的使用。
# 导入Callable和Sequence模块
# 以便使用可调用对象类型和序列类型进行类型注解
from typing import Callable, Sequence

# 定义一个名为apply_function的函数,接受以下两个参数:
#   func: 类型为Callable[[int, int], int],表示接收一个接受两个整数参数并返回一个整数的可调用对象(如函数)
#   numbers: 类型为Sequence[int],表示接收一个包含整数的不可变序列(如列表、元组等)
# 函数返回一个List[int]类型的结果,即一个整数列表
def apply_function(
    func: Callable[[int, int], int],
    numbers: Sequence[int]
) -> List[int]:
    # 使用列表推导式,遍历numbers中的每个整数num
    # 对于每个num,调用func(num, num)并将结果添加到新列表中
    # 最终返回这个包含func计算结果的新列表,其元素类型为int
    return [func(num, num) for num in numbers]

【四】 类型注解的应用

【1】函数参数和返回值的注解

# 定义一个名为add的函数,接受两个整数参数a和b
# 函数返回值类型为int,表示计算结果是一个整数
def add(a: int, b: int) -> int:
    # 在函数体内,直接将传入的整数参数a和b相加
    # 然后使用return语句返回它们的和
    # 这个返回值满足函数定义时指定的int类型
    return a + b

【2】类型注解的类成员

# 定义一个名为MyClass的类
class MyClass:
    # 类中定义一个名为value的实例变量,类型为int
    value: int

    # 定义类的构造方法(初始化方法)__init__
    # 接受一个名为initial_value的参数,类型为int
    # 构造方法无返回值,用None表示
    def __init__(self, initial_value: int) -> None:
        # 在构造方法内部,使用self关键字引用当前实例,并将传入的initial_value赋值给实例的value属性
        self.value = initial_value

    # 定义一个名为double_value的方法,该方法属于MyClass类
    # 方法无参数,返回值类型为int
    def double_value(self) -> int:
        # 在方法体内,使用self关键字引用当前实例,并访问其value属性
        # 将value属性值乘以2,然后返回计算结果
        # 返回值满足方法定义时指定的int类型
        return self.value * 2

【3】生成器函数的注解

# 导入typing模块中的Generator类型
from typing import Generator

# 定义一个名为generate_numbers的函数,接受一个类型为int的参数n
# 函数返回值类型声明为Generator,具体为Generator[int, None, None]
def generate_numbers(n: int) -> Generator[int, None, None]:
    # 使用for循环遍历从0到n-1(包含n-1)的整数序列
    for i in range(n):
        # 在循环体内使用yield语句生成一个值
        # yield语句使得函数成为一个生成器(Generator),在每次迭代时返回一个值并保持状态
        # 本次迭代生成的值为i,类型为int,满足Generator定义时的第一个类型参数
        yield i

【五】高级类型注解

【1】递归类型注解

  • List、Dict等类型的嵌套和组合。
# 导入typing模块中需要使用的List、Dict、Union类型
from typing import List, Dict, Union

# 定义一个类型别名Tree,表示树状结构的数据类型
# Tree由List构成,列表元素为Union[int, Dict[str, 'Tree']],即元素可以是整数或嵌套的字典,字典键为字符串,值为Tree类型
Tree = List[Union[int, Dict[str, 'Tree']]]

【2】类型别名

  • 自定义类型别名提高代码可读性。
# 定义两个类型别名,用于标识特定的数据类型
UserId = int
Username = str

# 定义get_user_details函数,接受一个类型为UserId的参数user_id
# 函数返回值类型为Tuple[UserId, Username],表示返回一个元组,包含一个UserId类型的元素和一个Username类型的元素
def get_user_details(user_id: UserId) -> Tuple[UserId, Username]:
    # 在这里编写获取用户详细信息的代码逻辑
    # ...
    # 假设已实现逻辑,返回一个包含用户ID和用户名的元组
    return (user_id, "username_value")  # 用实际用户名替换"username_value"

【3】类型检查工具

使用mypy等静态类型检查工具进行类型检查。

$ mypy your_program.py

【4】注意事项

  • 静态类型检查工具辅助,不会影响Python的动态特性,可以选择性地使用类型注解。
  • 类型注解应该让代码更易于理解,但不应使代码变得过于复杂。

【六】总结

  • typing模块为Python添加了静态类型注解的能力,提高了代码的可读性和维护性。
  • 本文介绍了类型注解的基本概念、常见类型和高级类型,以及类型检查工具的使用。
  • 希望读者可以更好地应用类型注解,改善Python代码的质量。
posted on 2026-06-05 19:23  leonZhang123  阅读(7)  评论(0)    收藏  举报