python 编码中为什么要写类型注解?

1、背景

我们先谈谈为什么在Python编码过程中强烈推荐使用类型注解 ?

Python对于初学者来说是非常好上手,原因是在于对计算机底层原理的高度封装和动态语言的特性使得Python用起来非常的舒适。但这种“舒适”是有代价的,我们可能听说过一句形容动态语言的话,动态一时爽,一直动态一直爽。为什么会这么说?动态的确会赋予我们在编码时更多的灵活性与能力,但是动态带来的是更多的不确定性及混乱,导致了后来的维护者甚至作者自己都会产生很大的维护压力(可以想象一个经过几年迭代的复杂系统,如果大部分都使用动态的方式来编写代码的样子),正所谓能力越大责任越大,需要进行克制;

而类型注解能很好的帮我们在维护与开发时,理清变量类型降低不确定性和混乱度,并且从容的使用变量。在这里废话了这么多,主要是为了能让读者能深刻意识到动态带来的正反方向带来的“爽”。后面进入正题;

2、使用方式

2.1、 Python3内置的类型注解

内置注解肯能大家都接触过,但总感觉很麻烦,导致后面很容易就放弃写注解,这是因为得到不正反馈,看如下示例:

a: str = "aa"
b: int = 1

# 参数和返回标注了类型,那么接下来调用时就能进行提示
def example(a: str) -> str:
 return f"Hello {a}"

pirnt(example("world"))

# # 一些简单的标注,看起来起不到效果,但如果换个有含义的名字呢
User = str
Age = int
Answer = str

def say_hello(u: User) -> Answer:
 return f"Hello {u}"

print(say_hello("Shadow"))

上面简单演示了内置的类型注解是如何使用的,但是其实这么简单的类型注解并不能帮助我们很好的标注变量;下面介绍一个typing模块

2.2、typing 模块的快速入门

typing 模块是类型注解的主角,Python运行时不强制执行函数和变量类型注解,但这些注解可用于类型检查器、IDE、静态检查器等第三方工具。这些第三方工具会在我们编码时进行提示与纠错;

下面提供一些日常使用到的方法与用例给大家参考:

import typing

# 自定义类型注解
User = str
Age = int

# 定义有多种类型注解的类型
AnyStr = typing.TypeVar('AnyStr', str, bytes)
a_str: AnyStr = "a"
a_bytes: AnyStr = b"a"

# 通用类型, 接收通用的类型,尽量少的去使用
def example_1(a: typing.Any):
  print(a)

"""
typing 模块是允许使用下标来辅助标记类型
"""

# 列表, 下标为列表的属性
def example_2(a_list: typing.List[User]) -> typing.List[str]:
  pass

# 字典,下标第一个为key,第二个为value
def example_3(a_dict: typing.Dict[User, Age]) -> typing.Dict[str, int]:
  pass

# 元祖,下标为元祖的属性
def example_4(a_tuple: typing.Tuple[User] = None) -> typing.Tuple[User]:
  pass

# Union, 在一些场景下我们某些参数或返回值是不确定,至少给定一个参数类型
def example_5(a_b: typing.Union[str, int]) -> typing.Union[str, int]:
  pass

# Optional, 与Union 有点类似,但默认多带一个None,至少给定一个参数类型
# 如:Optional[str] 等价于 Union[str, None]
def example_6(a: str) -> typing.Optional[str]:
  pass

# Tuple, 返回值有多个的时候, 如需要返回str, int, bool, float
def example_7() -> typing.Tuple[str, int, bool, float]:
  pass

# class, 类本身也是一种类型
class Action:

  up: str = "up"
  down: str = "down"

# 指定需求一个action对象的参数
def example_8(action_obj: Action) -> Action:
  pass

# 这样在一些枚举参数的场景下,我们也可以使用类作为我们枚举参数的归类
def example_9(action_cls: Action) -> Action:
  pass

# 如果上面的枚举参数你觉得并不能很好的实现,那么还是可以使用自定义类型注解的方式去实现
Action = str
up: Action = "up"
down: Action = "down"

# 在python3.9 中对枚举参数类型有更好的支持
MODE = type.Literal['r', 'rb', 'w', 'wb']
def open_file(file: str, mode: MODE) -> str:
  pass

open_file('/some/path', 'r') # 正常
open_file('/other/path', 'typo') # 会提示该类型不合法

# Type, 在一些多态类的场景下标注同一个类型的不同的形态
class User: ...

class BasicUser(User): ...

class ProUser(User): ...

class TeamUser(User): ...

# 相当于 typing.Union[User, BasicUser, ProUser, TeamUser]
def make_new_user(user_class: typing.Type[User]) -> User:
  return user_class()

以上十几个用例场景基本能覆盖大部分日常编码,如果还有一些别的需求可参考官方的文档,上面有明确的说明;

Docs: docs.python.org/zh-cn/3/lib…

3、写在最后

希望文章能对大家对类型注解的了解与使用有所帮助,早日脱离被动态绕得心里“骂娘”与找不到"娘"的日子。

以上就是python 编码中为什么要写类型注解?的详细内容,更多关于python 类型注解的资料请关注我们其它相关文章!

(0)

相关推荐

  • Python使用functools实现注解同步方法

    在 Python 中没有类似 Java 中使用的 synchronized 关键字来同步方法,因此在 Python 中要实现同步方法,通常我们是使用 threading.Lock() 来实现.在进入函数的地方获取锁,出函数的时候释放锁,这样实现代码看起好非常不好看.另外网上也有人给出了其它几种实现方式,但看起来都不美气. 今天我在做项目的时候突然想到是不是可以通过 functools 来实现通过注解来标注方法为同步方法. 首先要求自己的类中有一个锁对象并且在类初始化的时候初始化这个锁对象,比如:

  • Python中typing模块与类型注解的使用方法

    实例引入 我们知道 Python 是一种动态语言,在声明一个变量时我们不需要显式地声明它的类型,例如下面的例子: a = 2 print('1 + a =', 1 + a) 运行结果: 1 + a = 3 这里我们首先声明了一个变量 a,并将其赋值为了 2,然后将最后的结果打印出来,程序输出来了正确的结果.但在这个过程中,我们没有声明它到底是什么类型. 但如果这时候我们将 a 变成一个字符串类型,结果会是怎样的呢?改写如下: a = '2' print('1 + a =', 1 + a) 运行结

  • 深入浅析Python 函数注解与匿名函数

    函数注解与匿名函数 关于函数参数的定义,调用以及函数参数的内容,在下面的文章中已经做了初步的介绍,有需要的可以访问进行了解: Python 函数 函数注解 在编写函数,当下肯定清楚函数如何使用的.若是函数较为复杂,过段时间,编写者有可能需要花一段时间去重新了解函数的使用,那其他使用者也同样会遇到这样的困惑. 所以当编写完函数后,可以为函数的参数添加一些额外的信息.这里给函数参数添加注解,能够提示程序员如何正确使用这个函数.如下示例: def add(x:int, y:int) -> int: '

  • python 编码中为什么要写类型注解?

    1.背景 我们先谈谈为什么在Python编码过程中强烈推荐使用类型注解 ? Python对于初学者来说是非常好上手,原因是在于对计算机底层原理的高度封装和动态语言的特性使得Python用起来非常的舒适.但这种"舒适"是有代价的,我们可能听说过一句形容动态语言的话,动态一时爽,一直动态一直爽.为什么会这么说?动态的确会赋予我们在编码时更多的灵活性与能力,但是动态带来的是更多的不确定性及混乱,导致了后来的维护者甚至作者自己都会产生很大的维护压力(可以想象一个经过几年迭代的复杂系统,如果大部

  • Python代码中引用已经写好的模块、方法的两种方式

    平时写的一些 Python 的代码,需要在其他模块里面复用.最粗狂的方法就是直接 copy 过去. 但这种方式太麻烦,copy 一堆代码,导致代码量也很多.copy 的也不爽. 下面就介绍两种方式,可以简洁明了地调用自己在其他模块写的代码. 个人推荐第二种方式. 方式一: 手动使用 sys 调用自己写的 Python 模块.方法 我的代码存在 E:\\PycharmProjects\\111 目录下.需要调用的代码是 mypy 下 my007.py 里的 funA() 方法. my007.py

  • 一篇文章带你了解python中的typing模块和类型注解

    目录 typing模块 Dict List Tuple set/AbstractSet Sequence NoReturn Any TypeVar NewType Callable Union Optional Generator 总结 function annotation 写法: 使用冒号 : 加类型代表参数类型 默认值参数示例:b: int = 2 使用 -> 加类型代表返回值类型 python解释器运行时并不会检查类型,类型不对也不会抛异常,仅仅是注解而已.示例: def plus(a:

  • 使用TypeScript类型注解的方法

    目录 类型注解 类型推导 TS和JS共有的数据类型 TS独有的数据类型 any unknown void never tuple 函数参数和返回值 类型断言 非空类型断言 字面量 类型缩小 总结 类型注解 TypeScript提供了很多数据类型,通过类型对变量进行限制,称之为类型注解,使用类型注解后,就不能够随意变更变量的类型. 以下代码定义了一个字符串类型的变量,如果把它更改为数字类型时,代码编译阶段就会直接报错,提示 “Type ‘number’ is not assignable to t

  • 使用TypeScript类型注解的方法详解

    目录 类型注解 类型推导 TS和JS共有的数据类型 TS独有的数据类型 any unknown void never tuple 函数参数和返回值 类型断言 非空类型断言 字面量 类型缩小 总结 类型注解 TypeScript提供了很多数据类型,通过类型对变量进行限制,称之为类型注解,使用类型注解后,就不能够随意变更变量的类型. 以下代码定义了一个字符串类型的变量,如果把它更改为数字类型时,代码编译阶段就会直接报错,提示 “Type ‘number’ is not assignable to t

  • 在Python 3中实现类型检查器的简单方法

    示例函数 为了开发类型检查器,我们需要一个简单的函数对其进行实验.欧几里得算法就是一个完美的例子: def gcd(a, b): '''Return the greatest common divisor of a and b.''' a = abs(a) b = abs(b) if a < b: a, b = b, a while b != 0: a, b = b, a % b return a 在上面的示例中,参数 a 和 b 以及返回值应该是 int 类型的.预期的类型将会以函数注解的形式

  • Python编码类型转换方法详解

    本文实例讲述了Python编码类型转换方法.分享给大家供大家参考,具体如下: 1:Python和unicode 为了正确处理多语言文本,Python在2.0版后引入了Unicode字符串. 2:python中的print 虽然python内部需要将文本编码转换为unicode编码来处理,而终端显示工作则由传统的Python字符串完成(实际上,Python的print语句根本无法打印出双字节的Unicode编码字符). python的print会对输出的unicode编码(对其它非unicode编

  • python编码总结(编码类型、格式、转码)

    本文详细总结了python编码.分享给大家供大家参考,具体如下: [所谓unicode] unicode是一种类似于符号集的抽象编码,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储.也就是它只是一种内部表示,不能直接保存.所以存储时需要规定一种存储形式,比如utf-8和utf-16等.理论上unicode是一种能够容纳全世界所有语言文字的编码方案.(其他编码格式不再多说) [所谓GB码] GB就是"国标"的意思,即:中华人民共和国国家标准.GB码是面向汉字的编码,包括

  • Java8中的类型注解浅析

    注解大家都知道,从java5开始加入这一特性,发展到现在已然是遍地开花,在很多框架中得到了广泛的使用,用来简化程序中的配置.那充满争议的类型注解究竟是什么?复杂还是便捷? 一.什么是类型注解 在java 8之前,注解只能是在声明的地方所使用,比如类,方法,属性:java 8里面,注解可以应用在任何地方,比如: 创建类实例 复制代码 代码如下: new @Interned MyObject(); 类型映射 复制代码 代码如下: myString = (@NonNull String) str; i

随机推荐