Python 之类型注解

news2025/7/19 15:51:23

类型注解允许开发者显式地声明变量、函数参数和返回值的类型。但是加不加注解对于程序的运行没任何影响(是非强制的,且类型注解不影响运行时行为),属于 有了挺好,没有也行。但是大型项目按照规范添加注解的话,对于后期开发和维护是很有帮助的,毕竟不用回退好几层去推断有些变量的类型。

与原生数据类型的区别

特性类型注解原生数据类型
本质仅为代码中的类型提示信息,不影响代码运行时的行为实际存储和操作数据的结构,决定了数据的操作方式和内存占用
作用提高代码可读性,辅助静态类型检查用于实际的数据存储和处理
定义方式在变量名后使用冒号和类型名称进行标注通过赋值语句创建具体的数据对象

为什么用注解

代码补全

PyCharm 能根据类型注解提供更准确的属性/方法建议(如知道 y: str 后,输入 y. 会提示 str 的方法)。

比如我读取一个 json 文件并 json.load 后进行处理,像下面这种,在调用 data 的 items() 方法时,PyCharm 是没有方法提示的(毕竟 PyCharm 没办法未卜先知,无法提前预测加载后的 data 是什么类型,这也能理解)。

import json


if __name__ == '__main__':
    data = json.load(open("data.json", encoding="utf-8"))
    for key1, value1 in data.items():
        for key2, value2 in value1.items():
            print(f"{key1}\t{key2}\t{value2}")

添加注解以后,代码补全提示就方便多了。 

import json
from typing import Dict


if __name__ == '__main__':
    data: Dict[str, Dict[str, str]]  # 提前添加对 data 的注解
    data = json.load(open("data.json", encoding="utf-8"))
    for key1, value1 in data.items():
        for key2, value2 in value1.items():
            print(f"{key1}\t{key2}\t{value2}")

类型提示

添加类型注解以后,如果赋值的数据类型和注解声明的类型不一致的话,PyCharm 会进行提示,能够一眼洞察类型不符的情况,提前发现错误,避免运行时因类型错误导致的 TypeError 报错

维护方便

在多人协作或长期项目中,类型注解降低了理解代码的门槛,减少因类型混淆导致的 Bug,对于后期维护很有帮助。 

可读性提高

类型注解明确声明了参数和返回值的预期类型,使函数接口的语义一目了然。例如 def get_user(id: int) -> User 比未注解的版本更清晰,减少对参数类型的文字描述。

基础类型注解

Python 内置的基本类型可以直接用于注解。

# 变量注解
name: str = "Alice"
age: int = 30
price: float = 19.99
is_active: bool = True


# 函数参数和返回值注解
def greet(name: str) -> str:
    return f"Hello, {name}"


if __name__ == '__main__':
    name = "Looking"
    print(type(name))  # <class 'str'>
    greet_word = greet(name)
    print(greet_word)  # Hello, Looking

复合类型注解

from typing import List, Dict, Tuple, Set, Optional

# 列表
numbers: List[int] = [1, 2, 3]

# 字典
person: Dict[str, str] = {"name": "Alice", "email": "alice@example.com"}

# 元组 (固定长度和类型)
point: Tuple[float, float] = (3.14, 2.71)

# 集合
unique_numbers: Set[int] = {1, 2, 3}

# 可选类型 (表示 middle_name 有值的时候是 str,无值的时候可以是 None)
middle_name: Optional[str] = None

函数类型注解

from typing import Callable


# 基本函数注解
def add(a: int, b: int) -> int:
    return a + b


# 带默认值的参数
def greet(name: str, greeting: str = "Hello") -> str:
    return f"{greeting}, {name}"


# 函数作为参数
def apply_func(func: Callable[[int, int], int], x: int, y: int) -> int:
    return func(x, y)


if __name__ == '__main__':
    v1 = add(1, 2)
    print(v1)  # 3
    v2 = greet("Looking")
    print(v2)  # Hello, Looking
    v3 = apply_func(add, 2, 3)
    print(v3)  # 5

特殊类型注解

from typing import Any, Union, NoReturn, NewType


# Any - 任意类型
def log(message: Any) -> None:
    print(message)


# Union - 多个可能的类型
def square(number: Union[int, float]) -> Union[int, float]:
    return number ** 2


# NoReturn - 函数不会正常返回
def fail() -> NoReturn:
    raise Exception("Something went wrong")


UserId = NewType("UserId", int)
if __name__ == '__main__':
    log(123)  # 123
    log("hello world")  # hello world
    print(square(5))  # 25
    print(square(2.5))  # 6.25
    # UserId("hello")  # 类型检查不通过
    print(UserId(12345))  # 12345
    fail()
    # Traceback (most recent call last):
    #   File "E:\lky_project\tmp_project\test.py", line 24, in <module>
    #     fail()
    #   File "E:\lky_project\tmp_project\test.py", line 16, in fail
    #     raise Exception("Something went wrong")
    # Exception: Something went wrong

类型注解别名

from typing import List, Tuple

# 简单别名
UserId = int

# 复杂别名
Point = Tuple[float, float]
Vector = List[float]


def distance(point1: Point, point2: Point) -> float:
    return ((point1[0] - point2[0]) ** 2 + (point1[1] - point2[1]) ** 2) ** 0.5


def normalize(vector: Vector) -> Vector:
    length = sum(x ** 2 for x in vector) ** 0.5
    return [x / length for x in vector]


if __name__ == '__main__':
    point1 = (3, 4)
    point2 = (0, 0)
    print(distance(point1, point2))  # 5.0

    vector = [3, 4]
    print(normalize(vector))  # [0.6, 0.8]

泛型类型注解

from typing import TypeVar, Generic, List

T = TypeVar('T')  # 声明无约束的类型变量


class Stack(Generic[T]):
    def __init__(self) -> None:
        self.items: List[T] = []

    def push(self, item: T) -> None:
        self.items.append(item)

    def pop(self) -> T:
        return self.items.pop()


if __name__ == '__main__':
    # 使用
    int_stack = Stack[int]()  # 初始化实例并指定 T 的类型
    int_stack.push(12345)
    print(int_stack.items)  # [12345]

    str_stack = Stack[str]()
    str_stack.push("hello")
    print(str_stack.items)  # ['hello']

类型变量

from typing import TypeVar

# 无约束的类型变量(表明 T 可以是无约束的任何类型)
T = TypeVar('T')

# 有约束的类型变量
Number = TypeVar('Number', int, float, complex)


def double(x: Number) -> Number:
    return x * 2


def triple(x: T) -> T:
    return x * 3


if __name__ == '__main__':
    print(double(123))  # 246
    print(triple("hello "))  # hello hello hello

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2378181.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【linux】Web服务—搭建nginx+ssl的加密认证web服务器

准备工作 步骤&#xff1a; 一、 新建存储网站数据文件的目录 二、创建一个该目录下的默认页面&#xff0c;index.html 三、使用算法进行加密 四、制作证书 五、编辑配置文件&#xff0c;可以选择修改主配置文件&#xff0c;但是不建议 原因如下&#xff1a; 自定义一个配置文…

基于HTTP头部字段的SQL注入:SQLi-labs第17-20关

前置知识&#xff1a;HTTP头部介绍 HTTP&#xff08;超文本传输协议&#xff09;头部&#xff08;Headers&#xff09;是客户端和服务器在通信时传递的元数据&#xff0c;用于控制请求和响应的行为、传递附加信息或定义内容类型等。它们分为请求头&#xff08;Request Headers&…

实战解析MCP-使用本地的Qwen-2.5模型-AI协议的未来?

文章目录 目录 文章目录 前言 一、MCP是什么&#xff1f; 1.1MCP定义 1.2工作原理 二、为什么要MCP&#xff1f; 2.1 打破碎片化的困局 2.2 实时双向通信&#xff0c;提升交互效率 2.3 提高安全性与数据隐私保护 三、MCP 与 LangChain 的区别 3.1 目标定位不同 3.…

RabbitMQ高级篇-MQ的可靠性

目录 MQ的可靠性 1.如何设置数据持久化 1.1.交换机持久化 1.2.队列持久化 1.3.消息持久化 2.消息持久化 队列持久化&#xff1a; 消息持久化&#xff1a; 3.非消息持久化 非持久化队列&#xff1a; 非持久化消息&#xff1a; 4.消息的存储机制 4.1持久化消息&…

fpga系列 HDL : Microchip FPGA开发软件 Libero Soc 项目仿真示例

新建项目 项目初始界面中创建或导入设计文件&#xff1a; 新建HDL文件 module test (input [3:0] a,input [3:0] b,output reg [3:0] sum,output reg carry_out );always (*) begin{carry_out, sum} a b; endendmodule点击此按钮可进行项目信息的重新…

DeepSearch:WebThinker开启AI搜索研究新纪元!

1&#xff0c;项目简介 WebThinker 是一个深度研究智能体&#xff0c;使 LRMs 能够在推理过程中自主搜索网络、导航网页&#xff0c;并撰写研究报告。这种技术的目标是革命性的&#xff1a;让用户通过简单的查询就能在互联网的海量信息中进行深度搜索、挖掘和整合&#xff0c;从…

springCloud/Alibaba常用中间件之Setinel实现熔断降级

文章目录 SpringCloud Alibaba:依赖版本补充Sentinel:1、下载-运行&#xff1a;Sentinel(1.8.6)下载sentinel&#xff1a;运行&#xff1a;Sentinel <br> 2、流控规则① 公共的测试代码以及需要使用的测试Jmeter①、流控模式1. 直接:2. 并联:3. 链路: ②、流控效果1. 快速…

Deeper and Wider Siamese Networks for Real-Time Visual Tracking

现象&#xff1a; the backbone networks used in Siamese trackers are relatively shallow, such as AlexNet , which does not fully take advantage of the capability of modern deep neural networks. direct replacement of backbones with existing powerful archite…

黑马程序员C++2024版笔记 第0章 C++入门

1.C代码的基础结构 以hello_world代码为例&#xff1a; 预处理指令 #include<iostream> using namespace std; 代码前2行是预处理指令&#xff0c;即代码编译前的准备工作。&#xff08;编译是将源代码转化为可执行程序.exe文件的过程&#xff09; 主函数 主函数是…

foxmail - foxmail 启用超大附件提示密码与帐号不匹配

foxmail 启用超大附件提示密码与帐号不匹配 问题描述 在 foxmail 客户端中&#xff0c;启用超大附件功能&#xff0c;输入了正确的账号&#xff08;邮箱&#xff09;与密码&#xff0c;但是提示密码与帐号不匹配 处理策略 找到 foxmail 客户端目录/Global 目录下的 domain.i…

Crowdfund Insider聚焦:CertiK联创顾荣辉解析Web3.0创新与安全平衡之术

近日&#xff0c;权威金融科技媒体Crowdfund Insider发布报道&#xff0c;聚焦CertiK联合创始人兼CEO顾荣辉教授在Unchained Summit的主题演讲。报道指出&#xff0c;顾教授的观点揭示了Web3.0生态当前面临的挑战&#xff0c;以及合规与技术在推动行业可持续发展中的关键作用。…

PowerBI链接EXCEL实现自动化报表

PowerBI链接EXCEL实现自动化报表 曾经我将工作中一天的工作缩短至2个小时&#xff0c;其中最关键的一步就是使用PowerBI链接Excel做成一个自动化报表&#xff0c;PowerBI更新源数据&#xff0c;Excel更新报表并且保留报表格式。 以制作一个超市销售报表为例&#xff0c;简单叙…

腾讯云MCP数据智能处理:简化数据探索与分析的全流程指南

引言 在当今数据驱动的商业环境中&#xff0c;企业面临着海量数据处理和分析的挑战。腾讯云MCP(Managed Cloud Platform)提供的数据智能处理解决方案&#xff0c;为数据科学家和分析师提供了强大的工具集&#xff0c;能够显著简化数据探索、分析流程&#xff0c;并增强数据科学…

Android framework 中间件开发(一)

在Android开发中,经常会调用到一些系统服务,这些系统服务简化了上层应用的开发,这便是中间件的作用,中间件是介于系统和应用之间的桥梁,将复杂的底层逻辑进行一层封装,供上层APP直接调用,或者将一些APP没有权限一些操作放到中间件里面来实施. 假设一个需求,通过中间件调节系统亮…

MATLAB中的概率分布生成:从理论到实践

MATLAB中的概率分布生成&#xff1a;从理论到实践 引言 MATLAB作为一款强大的科学计算软件&#xff0c;在统计分析、数据模拟和概率建模方面提供了丰富的功能。本文将介绍如何使用MATLAB生成各种常见的概率分布&#xff0c;包括均匀分布、正态分布、泊松分布等&#xff0c;并…

C# 面向对象 构造函数带参无参细节解析

继承类构造时会先调用基类构造函数&#xff0c;不显式调用基类构造函数时&#xff0c;默认调用基类无参构造函数&#xff0c;但如果基类没有写无参构造函数&#xff0c;会无法调用从而报错&#xff1b;此时&#xff0c;要么显式的调用基类构造函数&#xff0c;并按其格式带上参…

在 C# 中将 DataGridView 数据导出为 CSV

在此代码示例中&#xff0c;我们将学习如何使用 C# 代码将 DataGridView 数据导出到 CSV 文件并将其保存在文件夹中。 在这个程序中&#xff0c;首先&#xff0c;我们必须连接到数据库并从中获取数据。然后&#xff0c;我们将在数据网格视图中显示该数据&#xff0c;…

MySQL中表的增删改查(CRUD)

一.在表中增加数据&#xff08;Create&#xff09; INSERT [INTO] TB_NAME [(COLUMN1,COLUMN2,...)] VALUES (value_list1),(value_list2),...;into可以省略可仅选择部分列选择插入&#xff0c;column即选择的列&#xff0c; 如图例可以选择仅在valuelist中插入age和id如果不指…

项目思维vs产品思维

大家好&#xff0c;我是大明同学。 这期内容&#xff0c;我们来聊一下项目思维和产品思维的区别。 项目是实施关键&#xff0c;力求每一步都精准到位&#xff1b;产品则是战略导向&#xff0c;确保所选之路正确无误。若缺乏优异成果&#xff0c;即便按时完成&#xff0c;也只…

游戏引擎学习第285天:“Traversables 的事务性占用”

回顾并为当天的工作做准备 我们有一个关于玩家移动的概念&#xff0c;玩家可以在点之间移动&#xff0c;而且当这些点移动时&#xff0c;玩家会随之移动。现在这个部分基本上已经在工作了。我们本来想实现的一个功能是&#xff1a;当玩家移动到某个点时&#xff0c;这个点能“…