首页 > 编程语言 >Python3类型安全type hint

Python3类型安全type hint

时间:2024-12-15 16:43:05浏览次数:4  
标签:hint int str typing 类型 import type Python3

type hint大纲

  1. 什么是类型安全以及我们为什么需要类型安全

  2. 如何使用Python3的type hint

  3. 老项目如何逐步引入type hint

  4. Type hint在运行时的应用

疑问

type hint在编译时会被去掉吧?

是的,Python的类型提示(Type Hints)只是一种语法糖,它们不会影响Python代码的运行。类型提示在运行时并不会进行类型检查,也不会影响代码的性能。它们主要是用来帮助程序员理解函数期望的输入和输出类型,以及提供给静态类型检查工具和IDE使用,以帮助找出潜在的错误。


类型标注能让我的程序运行得更快吗?

不会,Python的类型标注(Type Hints)并不会让你的程序运行得更快。类型标注在Python中主要是用于静态类型检查,以及提高代码的可读性和可维护性。它们在运行时并不会进行任何类型检查,也不会改变Python的动态类型特性,因此不会影响程序的运行速度。如果你想提高Python程序的运行速度,可以考虑使用如Cython、PyPy等工具,或者优化你的算法和数据结构。


为什么新的语言大部分都选择了类型在变量名的后面?

//Rust:
fn greeting(name: &str) -> String {
}

//Go:
func greeting(name string) string {
}

//Typescript:
function greeting(name: string): string {
}

python3的type check

Literal 在Python3中,字面量(Literal)是指在代码中直接使用的特定值。字面量可以是数字字面量,字符串字面量,布尔字面量,特殊字面量,或者容器字面量

Autocomplete 自动补全

添加type hint的位置
• 函数/方法签名
• 变量初始化

name: str = "Python3"
name = "Python3" # type checker know it’s a str
def greeting(name: str) -> str
	return 'Hello ' + name

多种类型(Union)

from typing import Union
def accept_task(task_id: int) -> None:
    task_type: Union[str, int]
    if is_side_task(task_id):
        task_type = "Side Task"
    else:
		task_type = 1

可选import(Optional)

from typing import Optional
def accept_task(task_id: int) -> None:
    task_type: Optional[str] #这两种可选写法都ok
    task_type: str | None #这两种可选写法都ok
    if is_side_task(task_id):
        task_type = "Side Task"
    else:
        task_type = None

条件import(TYPE_CHECKING)

原来的import存在以下问题:

from data.config.monster import MonsterConfig
def spawn_monster(monster: MonsterConfig) -> None:
	...

可能需要避免import的情况:
• 会造成循环import
• Import有side-effect或者特定的时机要求
• Import耗时太长

增加条件后的import

from __future__ import annotations
import typing
if typing.TYPE_CHECKING:
	from data.config.monster import MonsterConfig
def spawn_monster(monster: MonsterConfig) -> None:
	...

前向引用(前向声明)

类用字符串来代替?或者导入annotations

NewType

在Python中,类型别名是一个方便的方式,用于为复杂的类型标注提供一个简单的名称。你可以使用 typing.TypeVartyping.NewType 创建类型别名。

例如,如果你有一个复杂的类型,如 List[Tuple[str, str, int]],你可以创建一个类型别名来简化它:

from typing import List, Tuple, TypeVar

PersonInfo = List[Tuple[str, str, int]]

def get_people_info() -> PersonInfo:
    return [('Alice', 'Engineer', 30), ('Bob', 'Doctor', 40)]

在这个例子中,PersonInfo 是一个类型别名,代表 List[Tuple[str, str, int]] 类型。这样可以使代码更易读,更易维护。

Callable

在Python中,typing模块提供了Callable,这是一个类型提示,用于表示可调用的类型,比如函数或方法。

下面是一个使用Callable的例子:

from typing import Callable

def apply_func(x: int, func: Callable[[int], int]) -> int:
    return func(x)

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

print(apply_func(5, double))  # 输出:10

在这个例子中,apply_func函数接受一个整数x和一个函数func作为参数。func的类型被注解为Callable[[int], int],这表示它是一个接受一个整数参数并返回一个整数的函数。double函数就是这样一个函数,所以我们可以将它作为apply_func的参数。

Protocol

由于python函数中的参数无类型,或者说我们不关心对象的类型只关心它能做什么,所以可以通过隐式或某个规则来绕过typing的检查?

在Python 3.8及以上版本中,typing模块提供了Protocol类,它是一种特殊的类,用于定义结构化的类型协议。如果一个类满足了Protocol的定义,那么它就被认为是实现了该协议,无论它是否显式地继承了Protocol

下面是一个使用Protocol的例子:

from typing import Protocol

class SupportsClose(Protocol):
    def close(self) -> None:
        ...

def close_resource(resource: SupportsClose) -> None:
    resource.close()

class Resource:
    def close(self) -> None:
        print("Resource closed")

resource = Resource()
close_resource(resource)  # 输出:Resource closed

在这个例子中,SupportsClose是一个Protocol,它定义了一个close方法。close_resource函数接受一个SupportsClose类型的参数。尽管Resource类并没有显式地继承SupportsClose,但是它实现了close方法,所以它被认为是实现了SupportsClose协议,可以作为close_resource的参数。

泛型Generic

在Python 3中,typing模块提供了Generic类,用于定义泛型类型。泛型类型是指在定义时不指定具体类型,而在实例化时才确定具体类型的类型。

下面是一个使用Generic的例子:

from typing import Generic, TypeVar

T = TypeVar('T')

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

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

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

# 使用时指定具体类型
stack = Stack[int]()
stack.push(1)
print(stack.pop())  # 输出:1

在这个例子中,Stack是一个泛型类,它接受一个类型参数T。在实例化Stack时,我们需要指定T的具体类型。例如,Stack[int]()创建了一个只接受int类型元素的栈。

使用泛型可以提高代码的复用性,使得我们可以用一套代码来处理多种类型的数据。同时,它也可以提高类型安全性,因为我们可以在编译时检查类型的正确性。

协变与逆变Covariant & Contravariant

变成c++的写法了?这个章节的内容非常多

Mypy Plugin

目前使用最多的pright,由微软主导是vscode自带的

mypy使用的较少

https://mypy.readthedocs.io/en/stable/extending_mypy.html
• 缺少文档
• 和其他type checker不兼容

Overload

如果项目比较特殊,非要使用mypy的话,通过overload来实现

pyi文件

只包含函数和变量类型“声明”的Python文件,Pyi文件的优先级高于py文件
使用场景:
• C/C++ extension模块的类型标注
• Python2/Python3兼容代码的类型标注
• Import耗时较长的模块的类型标注
• 为原本没有类型标注的第三方库添加类型标注
放置位置:
• 位于py文件同级目录
• 位于单独的stub目录(通过参数传递给type checker)

老项目引入 type checking

兼容老代码

迭代老代码

逐步将老的代码文件从exclude中移除
• 更新或为第三方库添加type hint
• 移除disable_error_code
• 单独跳过特定的第三方库

[[tool.mypy.overrides]]
module = "some_legacy_third_party"
follow_imports = skip

禁止未标注的新代码

运行时应用(Runtime API )

类型标注Annotation

import typing
typing.get_type_hints
typing.get_origin
assert get_origin(str) is None
assert get_origin(Dict[str, int]) is dict
assert get_origin(Union[int, str]) is Union
P = ParamSpec('P')
assert get_origin(P.args) is P
assert get_origin(P.kwargs) is P
typing.get_args
assert get_args(int) == ()
assert get_args(Dict[int, str]) == (int, str)
assert get_args(Union[int, str]) == (int, str)

PEP 563

PEP 563’s default change is clearly too disruptive to downstream users
and third-party libraries to happen right now. We can’t risk breaking even
a small subset of the FastAPI/pydantic users, not to mention other uses of
evaluated type annotations that we’re not aware of yet

PEP 563 的默认更改显然对下游用户和第三方库的破坏性太大,目前无法实现。我们不能冒险破坏 FastAPI/pydantic 用户的一小部分,更不用说我们尚不知道的评估类型注释的其他用途

Pydantic

定义每个class中字段的类型,强制指定类型和字段

FastAPI

调用者就相当于在使用强类型语言

Runtime API

Bevy Style ECS API

bevy是一个使用ecs模式的游戏引擎

Mypyc

Cython 3.0

使用cython在运行时热更替换C代码

总结

Type hint能够帮助我们提早发现程序中的类型错误
• 我们可以逐步分阶段在项目中引入type hint
• 我们可以在运行时合理的利用type hint
• Type hint可以帮助我们编译出性能更高的程序
• Python的type hint还在快速的发展中,要用动态的眼光去看代它

标签:hint,int,str,typing,类型,import,type,Python3
From: https://www.cnblogs.com/zhaoqingqing/p/18608123

相关文章

  • Python3 输入和输出
    介绍Python的输入输出。输出格式美化Python两种输出值的方式:表达式语句和print()函数。第三种方式是使用文件对象的write()方法,标准输出文件可以用sys.stdout引用。如果你希望输出的形式更加多样,可以使用str.format()函数来格式化输出值。如果你希望将输出......
  • maven - archetype - quickstart 和maven - archetype - archetype 和maven - archety
    maven-archetype-quickstart和maven-archetype-archetype区别功能重点不同maven-archetype-quickstart:主要功能是快速搭建一个简单的、可运行的Java应用程序框架。它的重点在于让开发者能够迅速开始编写Java代码,构建一个基本的、能够独立运行的程序,例如一个......
  • python3安装pandas
    检查安装环境检查python版本python--version检查pip版本pip--version检查安装列表piplist安装pandaspip3installpandas这是从官方下载安装,速度比较慢,可以使用国内镜像站清华:https://pypi.tuna.tsinghua.edu.cn/simple阿里云:http://mirrors.aliyun.com/py......
  • 机载电脑通过TypeC连接Pixhawk 6c (PX4)后的状态确认及问题解决
    在三个终端依次运行命令查看连接状态roscoeroslaunchmavrospx4.launchrostopicecho/mavros/state1.运行mavrospx4.lauch时udp1报错“networkisunreachable”原因:网关未设置解决方法:先通过使用route命令查看默认ip,发现网关未设置,再通过以下命令设置网关:sudorout......
  • HTTP content-type
    Content-Type(内容类型),一般是指网页中存在的Content-Type,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件,这就是经常看到一些PHP网页点击的结果却是下载一个文件或一张图片的原因。Content-Type标头告诉客户端实际返回的内容的内容类型。......
  • 【他山之石】Leading-Trim: The Future of Digital Typesetting:数字排版的未来 —— L
    文章目录【他山之石】Leading-Trim:TheFutureofDigitalTypesetting:数字排版的未来——Leading-TrimHowanemergingCSSstandardcanfixoldproblemsandraisethebarforwebapps1.Theproblemwithtextboxestoday2.Howwegothere:ahistorylesso......
  • Python3 insloader库爬取博主视频粉丝量,点赞,互动率,国家等信息
    写在题前:之前搞Java的,今天部门的人给了我一批视频链接,问问有没有办法爬出来这一批视频链接的博主的粉丝量,以及该视频的互动率等信息。经过一番探索之后了解了insloader库。真不不得不感叹python的强大。 之前给代码把:importinstaloaderfromurllib.parseimporturlpars......
  • 自定义typeHandler将包含经纬度对象插入到mysql的point类型的字段中
    博客:https://www.emanjusaka.top公众号:emanjusaka的编程栈下面给出关键部分代码,完整代码请访问原文地址mysql中的point类型在java中没有对应的类型匹配,需要我们自定义typeHandler去处理。环境参数SpringBootMybatisPlusmysql代码实现typeHandlerGeomPointTyp......
  • Python3 条件控制
    Python条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块。可以通过下图来简单了解条件语句的执行过程:代码执行过程:if语句Python中if语句的一般形式如下所示:ifcondition_1:statement_block_1elifcondition_2:statement_block_2else......
  • Typescript
    Typescript教程_Typescript视频教程ts入门实战视频教程-2021年更新包含Vue3+Tshttps://www.bilibili.com/video/BV1yt411e7xV?from=search&seid=9050004695350176192https://www.itying.com/category-85-b0.htmlhttps://blog.csdn.net/z591391960/article/details/105667767......