首页 > 编程语言 >13.Python3 类型注解

13.Python3 类型注解

时间:2025-01-15 18:56:32浏览次数:1  
标签:13 int Python user str typing 类型 注解 Python3

Python3 类型注解

Python 类型注解(Type Hints)是自 Python 3.5 引入的一种特性,它允许开发者在定义函数、变量时指定数据类型。类型注解并非强制执行的,它们主要用于提高代码的可读性和可维护性,并支持静态分析工具进行类型检查。类型注解不会影响 Python 的动态特性,也不会在运行时被强制执行,尤其是在大型项目中可以帮助开发者减少错误。

Python 类型注解文档:https://docs.python.org/zh-cn/3.13/library/typing.html

1. 基本语法

类型注解的基本语法包括在变量声明或函数定义中使用冒号 : 来指定参数的类型,并且使用箭头 -> 来指明函数的返回值类型

变量注解:

# 内置类型注解 int, float, bool, str
age: int = 20

# Python 3.9+
items: list[int] = [1, 2, 3]

# Python 3.8及以下版本
from typing import List, Dict, Tuple, Set
# 列表中元素为整数
numbers: List[int] = [1, 2, 3]
# 字典键为字符串,值为浮点数
prices: Dict[str, float] = {"apple": 2.5, "banana": 1.2}
# 元组内有两个元素,分别是字符串和整数
pair: Tuple[str, int] = ("hello", 42)
# 集合中元素为布尔值
flags: Set[bool] = {True, False}

对于内置类型如 int, float, bool, str 等,可以直接使用这些类型作为注解。此外,Python 还提供了对容器类型的支持,比如列表 list、元组 tuple、字典 dict 和集合 set。在 Python 3.9 及以上版本中,可以直接使用标准库中的容器类型进行类型注解;而在更早的版本中,则需要从 typing 模块导入相应的泛型容器类型。

函数注解:

def greet(name: str) -> str:
    return 'Hello, ' + name

这里 name: str 表示期望传入的 name 参数是一个字符串,而 -> str 表示这个函数应该返回一个字符串。

2.复杂类型注解

除了简单的内置类型外,typing 模块还提供了更多复杂的类型构造器来创建复合类型。

1. Union 类型

Union 用来表示一个变量或函数参数可以接受多种类型中的任意一种。例如,如果一个函数既可以接收整数也可以接收字符串作为参数,我们可以这样写:

from typing import Union

def normalize_id(id: Union[int, str]) -> str:
    return str(id)
# 在这个例子中,`normalize_id` 函数的参数 `id` 可以是 `int` 或者 `str` 类型。

2. Optional 类型

Optional即表示一个变量可以是给定类型的值或者是 None。这对于可能为空的返回值或参数非常有用:

from typing import Optional

def get_first_element(lst: list) -> Optional[str]:
    if lst:
        return lst[0]
    else:
        return None
# get_first_element 函数的返回值可能是列表的第一个元素(假设是字符串)或者当列表为空时返回 `None`。

3. Callable 类型

Callable 用来描述一个可调用对象(如函数、方法或类),它指定了该对象接收的参数类型以及返回值类型。这有助于确保传递给其他函数的回调函数具有正确的签名:

from typing import Callable

def invoke_callback(callback: Callable[[int], str], value: int) -> str:
    return callback(value)

# 定义符合上述签名的回调函数
def stringifier(number: int) -> str:
    return f"Number is {number}"

# 调用 invoke_callback 并传入回调函数
result = invoke_callback(stringifier, 42)

# Callable[[Arg1Type, Arg2Type], ReturnType]
# Callable[[参数1类型,参数2类型], 返回值类型]

4. Literal 类型

Literal 用来限制变量只能取某些特定的字面量值。这对于配置选项、枚举值等场景特别有用,因为可以确保只允许预先定义好的几个值:

from typing import Literal

def set_mode(mode: Literal['read', 'write']) -> None:
    print(f"Mode set to {mode}")

set_mode('read')  # 正确
set_mode('execute')  # 错误,在静态分析时会被捕获

5. TypeAlias 类型

TypeAlias 允许为复杂类型创建别名,使得代码更加简洁且易于理解。从 Python 3.11 开始,TypeAlias 成为了正式的一部分,但在此之前可以通过简单的赋值来创建类型别名:

from typing import TypeAlias, List

# Python 3.11前直接赋值创建类型别名
vector = List[float]

# Python 3.11 后使用TypeAlias创建类型别名
Vector: TypeAlias = List[float]

def scale_vector(v: Vector, factor: float) -> Vector:
    return [x * factor for x in v]

vector_example: Vector = [1.0, 2.0, 3.0]
scaled_vector = scale_vector(vector_example, 2.0)

6. Any 类型

当不确定或者不关心具体的类型时,可以使用 Any 类型:

from typing import Any

def log(message: Any) -> None:
    print(message)

3. 协变与逆变

在 Python 的类型系统中,协变(Covariant)和逆变(Contravariant)用于描述类型之间的关系,特别是在容器类型中。

  • 协变:如果 CatAnimal 的子类,那么 List[Cat] 也可以被视为 List[Animal] 的子类。这种情况下,我们说 List 对其元素类型是协变的。
  • 逆变:对于某些类型的容器,如函数参数,如果我们有一个接受 Animal 类型参数的函数,那么它也能够接受接受 Cat 类型参数的函数作为参数。这里,函数参数位置上的类型是逆变的。

Python 的 typing 模块中,SequenceMapping 等类型默认是协变的,而 Callable 默认是逆变于输入参数且协变于返回值。

4.泛型类

TypeVar 用于创建类型变量,这些变量可以被用作泛型类型的参数。类型变量允许你在定义函数、类或方法时指定某些参数或返回值的类型可以是任意类型,但是调用者必须提供一个具体的类型来替代这个类型变量。TypeVar 主要用于定义泛型函数、类和容器。

from typing import TypeVar, List

T = TypeVar('T')  # 创建一个名为 T 的类型变量

def first_element(lst: List[T]) -> T:
    """Return the first element of a non-empty list."""
    return lst[0] if lst else None

在这个例子中,T 是一个类型变量,它表示 first_element 函数可以接受任何类型的列表,并且返回该列表中元素的相同类型。这意味着如果你传入一个 List[int],那么返回值也将是 int 类型;如果你传入 List[str],则返回值将是 str 类型。

5. NewType

NewType 是 Python 的 typing 模块提供的一个工具,用于创建名义上不同的类型。尽管这些新类型的值实际上与原始类型具有相同的底层表示,但在静态类型检查时,它们被视为完全不同的类型。这有助于提高代码的安全性和可读性,因为它可以防止在不应该的地方互换使用看似相似的类型。NewType 接受两个参数:第一个是新类型的名称,第二个是现有类型的引用。下面是一个简单的例子:

from typing import NewType

UserId = NewType('UserId', int)

def get_user_name(user_id: UserId) -> str:
    # 在这里实现获取用户名的逻辑
    return f"User {user_id}"

# 正确使用
user_id = UserId(42)
print(get_user_name(user_id))

# 错误使用(静态分析会捕捉到这个错误)
# print(get_user_name(42))  # 类型检查器将报告错误

在这个例子中,UserId 被定义为 int 的一种特殊形式。然而,在静态类型检查期间,UserIdint 将被视为不同的类型。因此,直接传递一个整数给 get_user_name 函数会导致类型检查错误,而传递一个 UserId 对象则是正确的。

6. 静态类型检查设置

对于 VSCode,通常只需要确保安装了 Python 扩展,并且启用了类型检查功能。可以在设置中搜索 Python › Analysis: Type Checking Mode 并选择 basicstrict 模式。测试代码:

from typing import NewType

UserId = NewType('UserId', int)

def get_user_name(user_id: UserId) -> str:
    return f"User {user_id}"

# 正确使用
user_id = UserId(42)
print(get_user_name(user_id))

# 错误使用
print(get_user_name(42))  # 类型检查器应报告错误

标签:13,int,Python,user,str,typing,类型,注解,Python3
From: https://www.cnblogs.com/littlecamel/p/18673603

相关文章

  • Android T(13) 源码分析 — 原生层 Surface 的创建
    AndroidT(13)源码分析—原生层Surface的创建文章目录AndroidT(13)源码分析—原生层Surface的创建前言摘要一、SurfaceComposerClient的createSurfaceChecked分析二、ISurfaceComposerClient的createSurface分析总结前言该系列文章基于AndroidT......
  • 20221320冯泰瑞《密码系统设计》第十二周
    20221320冯泰瑞《密码系统设计》第十二周学习内容HeadFirstC嗨翻C语言第12章课程mindmapAI对学习内容的总结要求让AI(kimi,元宝等)阅读学习内容并进行总结,教材内容可以使用微信读书或者云班课电子教材总结《HeadFirstC》第十二章的内容主要介绍了如何在C语言中使......
  • 20221320冯泰瑞—阅读习惯(选做)
    阅读习惯(选做)1.推荐参考批判性思维书单https://weread.qq.com/misc/booklist/3107758_7sb8Fs2Hv,机关公文写作书单https://weread.qq.com/misc/booklist/3107758_7TeJ68iPx,公务员素质书单https://weread.qq.com/misc/booklist/3107758_7usfrsrTZ从中选择阅读,养成阅读习惯2.提......
  • 20221320冯泰瑞《密码系统设计》第十周
    20221320冯泰瑞《密码系统设计》第十周学习内容HeadFirstC嗨翻C语言第10章课程mindmapAI对学习内容的总结要求让AI(kimi,元宝等)阅读学习内容并进行总结,教材内容可以使用微信读书或者云班课电子教材总结《HeadFirstC》第十章的内容主题是进程间通信(InterprocessC......
  • 20221320冯泰瑞《密码系统设计》第十一周
    20221320冯泰瑞《密码系统设计》第十一周学习内容HeadFirstC嗨翻C语言第11章课程mindmapAI对学习内容的总结要求让AI(kimi,元宝等)阅读学习内容并进行总结,教材内容可以使用微信读书或者云班课电子教材总结《HeadFirstC》第十一章的内容主要介绍了C语言中网络编程......
  • 国产化板卡设计原理图:2136-KC705E增强版基于FMC接口的 JFM7K325T PCIeX8 接口卡
    KC705E增强版基于FMC接口的JFM7K325TPCIeX8接口卡    一、板卡概述   本板卡基于FPGAJFM7K325T 芯片,pin_to_pin兼容FPGAXC7K410T-2FFG900 ,支持PCIeX8、64bit DDR3容量2GByte,HPC的FMC连接器,板卡支持各种接口输入,软件支持windows,Linux驱动。    二、功......
  • [数据结构学习笔记13] 递归简介(Recursion)
    递归让我们把问题由大分小,小到我们能够轻松处理。递归方法有两个要注意的点:1.递归方法会重复的被调用;2.必须有一个终止条件,否则方法调用不停,会导致stackoverflow。看下面的一个例子,这个没有终止条件,会报错!functionhello(){console.log("I'malittlefunction,shorta......
  • Python2.x和Python3.x的区别?
     Python3.x中,print语句没有了,取而代之的是print()函数,print语句Python编译器会报错Python2.x默认采用ASCII编码,而Python3.x默认采用UTF-8编码,可以很好的支持中文或者其它非英文字符。Python2.x中,/运算符的使用方式和Java/C语言累死,整数相除得整数,浮点数相除保留小......
  • 线性代数13.线性相关性&内积&范数&正交
    13.线性相关性&内积&范数&正交13.1向量组的线性相关性13.1.1定义对于任意向量组\(A:a_1,a_2,a_3,...,a_n\),存在不全为0的数\(k_i(i=1,2,3,...,m)\),使:\[\tag{1}\sum_{i=1}^mk_i\cdota_i=0\]则称向量组A是\(线性相关\)的,否则称A是\(线性无关\)的13.1.2线性相关示例示例......
  • 逐笔成交逐笔委托Level2高频数据下载和分析:20250113
    level2逐笔成交逐笔委托下载链接:https://pan.baidu.com/s/1MznaXomAMSfljBMwAF9CDA?pwd=2rkf提取码:2rkfLevel2逐笔成交逐笔委托数据分享下载 采用Level2逐笔成交与逐笔委托的详细记录,这种毫秒级别的数据能揭露众多关键信息,如庄家意图、虚假交易,使所有交易行为透明......