首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Python类型编程

Python类型编程

作者头像
明月AI
发布2021-10-28 14:51:35
发布2021-10-28 14:51:35
9950
举报
文章被收录于专栏:野生AI架构师野生AI架构师

Python是一种弱类型的解释性语言,以前在使用的时候往往也只是当作弱类型来使用。在开发小型系统的时候,弱类型也没什么问题,但是系统稍微复杂点,维护就可能会变成一个大坑。

不过自从Python3.6之后,已经加入了类型提示的功能,现在主流的版本也是3.8了,是时候该上马类型编程了。

一个简单的例子


先上一碟小菜:

代码语言:javascript
复制
def hello(name: str="world") -> str:
    msg = f"hello {name}"
    return msg

print(hello("deeao"))

不过这真的只是一个类型提示,随便传入一个值都不会进行参数校验:

代码语言:javascript
复制
print(hello(30))
print(hello([30]))

这也不会报错,这特性也挺让人失望的。

更复杂的类型


简单的类型,我们有bool,int,float,str等,也有复杂一点的tuple,list,set,dict等,不过这些几个复杂一点的类型的定义并不是太清晰,例如list,只知道是一个列表,却没有定义列表元素的类型。我们需要借助typing来定义更加清晰的数据结构:

代码语言:javascript
复制
from typing import Dict, List, Tuple, Set, Optional

# 定义向量类型,元素为float的列表
Vector = List[float]
# key和value的类型都是str
ConnectionOptions = Dict[str, str]
# 包含str和int两种类型的列表
Address = Tuple[str, int]
Server = Tuple[Address, ConnectionOptions]

def say_hi(name: Optional[str] = None):
    if name is not None:
        print(f"Hey {name}!")
    else:
        print("Hello World")

官方文档:https://docs.python.org/zh-cn/3/library/typing.html

特殊类型与特殊形式


  • typing.Tuple
  • 元组类型; Tuple[X, Y] 是二项元组类型,第一个元素的类型是 X,第二个元素的类型是 Y。空元组的类型可写为 Tuple[()]。 例:Tuple[T1, T2] 是二项元组,类型变量分别为 T1 和 T2。Tuple[int, float, str] 是由整数、浮点数、字符串组成的三项元组。 可用省略号字面量指定同质变长元组,例如,Tuple[int, ...]TupleTuple[Any, ...] 等价,也与 tuple 等价。
  • typing.Union
  • 联合类型;Union[X, Y] 的意思是,非 X 即 Y。 可用 Union[int, str] 等形式定义联合类型。具体如下:
    • 参数必须是某种类型,且至少有一个。
    • 联合类型之联合类型会被展平,例如: Union[Union[int, str], float] == Union[int, str, float]
    • 单参数之联合类型就是该参数自身,例如: Union[int] == int # The constructor actually returns int
    • 冗余的参数会被跳过,例如: Union[int, str, int] == Union[int, str]
    • 比较联合类型,不涉及参数顺序,例如: Union[int, str] == Union[str, int]
    • 联合类型不能作为子类,也不能实例化。
    • 不支持 Union[X][Y] 这种写法。
    • Optional[X]Union[X, None] 的缩写。
  • typing.Any
  • 不受限的特殊类型。
    • 所有类型都与 Any 兼容。
    • Any 与所有类型都兼容。
  • typing.NoReturn
  • 标记没有返回值的函数的特殊类型。例如: from typing import NoReturn def stop() -> NoReturn: raise RuntimeError('no way')
  • class typing.NamedTuple
  • collections.namedtuple() 的类型版本。 用法: class Employee(NamedTuple): name: str id: int 相当于: Employee = collections.namedtuple('Employee', ['name', 'id']) 为字段提供默认值,要在类体内赋值: class Employee(NamedTuple): name: str id: int = 3 employee = Employee('Guido') assert employee.id == 3 带默认值的字段必须在不带默认值的字段后面。
  • typing.NewType(name, tp)
  • 用于为类型检查器标明不同类型的辅助函数,详见 NewType。在运行时,它返回一个返回其参数的函数。用法如下: UserId = NewType('UserId', int) first_user = UserId(1)
  • class typing.TypedDict(dict)
  • 把类型提示添加至字典的特殊构造器。在运行时,它是纯 dictTypedDict 声明一个字典类型,该类型预期所有实例都具有一组键集,其中,每个键都与对应类型的值关联。运行时不检查此预期,而是由类型检查器强制执行。用法如下: class Point2D(TypedDict): x: int y: int label: str a: Point2D = {'x': 1, 'y': 2, 'label': 'good'} # OK b: Point2D = {'z': 3, 'label': 'bad'} # Fails type check assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first') 用于内省的类型信息可通过 Point2D.__annotations__Point2D.__total__ 访问。

FastAPI中的应用


FastAPI中的接口参数是有类型校验的,我猜应该是使用装饰器内使用反射实现的。

关于Python类型的小结


Python虽然有了类型提示,可依然是弱类型,仅仅是作为提示作用(不知道以后的版本会不会继续增强),跟强类型还是差了很远。

不过聊胜于无吧,能写出清晰的代码也是大功一件,而且各种编辑器的代码提示也得依赖类型提示来实现代码补全。

使用python开发系统,应该强制使用清晰的变量类型定义,即使小系统,也应该这样。(有些系统可能开始开发的时候,是个小系统,但是开发过程中,代码越来越多,就变成了一个复杂系统)

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-06-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 野生AI架构师 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档