使用 mypy 做 type check

news/2024/7/7 20:17:06

前言

完残!😂,最近看之前写的 Python 代码老得琢磨这比变量的类型是啥(Python 无类型系统xxx),不愧是我写的!

看段之前写的实现迭代器模式的代码:

# 抽象迭代器类
class Iterator(object):
    def hasNext():
        pass

    def next():
        pass

# 抽象聚集类
class Aggregate(object):
    def iterator():
        pass

class BookShelf(Aggregate):
    def __init__(self):
        self._books = []
        self._last = 0

    def getBookAt(self, index):
        return self._books[index]

    def appendBook(self, book):
        self._books.append(book)
        self._last = self._last + 1

    def getLength(self):
        return self._last

    def iterator(self):
        return BookShelfIterator(self)

class BookShelfIterator(Iterator):
    def __init__(self, bookShelf):
        self._bookShelf = bookShelf
        self._index = 0

    def hasNext(self):
        if self._index < self._bookShelf.getLength():
            return True
        else:
            return False

    def next(self):
        book = self._bookShelf.getBookAt(self._index)
        self._index = self._index + 1
        return book

class Book():
    def __init__(self, name):
        self._name = name

    def getName(self):
        return self._name

if __name__ == "__main__":
    bookShelf = BookShelf()
    bookShelf.appendBook(Book("A"))
    bookShelf.appendBook(Book("B"))
    bookShelf.appendBook(Book("C"))
    bookShelf.appendBook(Book("D"))

    it = bookShelf.iterator()
    while it.hasNext():
        book = it.next()
        print(book.getName())

有一丢丢难读(不通读的话,会乱猜某变量类型),回想之前在 PyCon China 2019 的大会资聊曾看到过类型检查相关的演讲主题,回顾下演讲视频。水一波,写篇文章了解下 Python 标准(PEP 3107 & PEP 484 )支持的 mypy。

类型系统:编译期的类型推导检查规则,类型系统属于一种轻量级的形式化方法(一种数学方法)

使用-mypy

# 安装 mypy
pip install mypy
# 使用 mypy 做类型检查
mypy module_name.py

以下使用方式适用于 Python 3.6 及以上的版本。值得注意:mypy 默认的推导类型不可为 None

变量的类型注释

integer: int = 1
string: str = "ShanSan"
err_str: str = 1  # error: Incompatible types in assignment
child: bool = True
# mypy 默认的推导类型不可为 None
none: int - None  # error: Invalid type comment or annotation

print(integer, string)

内建类型

关于更多 mypy 的类型系统内建的类型可参考:https://mypy.readthedocs.io/en/stable/builtin_types.html

from typing import Dict, Tuple, Optional, Iterable, Union
# 对于映射(Map)数据结构,需要指定 key 和 value 的类型
x: Dict[str, float] = {'field': 2.0}

# Tuple 需要指定所有元素的类型
x: Tuple[int, str, float] = (3, "yes", 7.5)

# error: Incompatible types in assignment (expression has type "Tuple[int, str, float, int]", variable has type "Tuple[int, str, float]")
y: Tuple[int, str, float] = (3, "yes", 7.5, 11)

op: Optional[str] = None  # 可为 str 或 None

# 泛用可迭代对象
l: Iterable = [1]
t: Iterable = (1, 2)
d: Iterable = {1: 1}

# 可为 str 或 int
str_int1: Union[str, int] = 1
str_int2: Union[str, int] = "ss"
str_int3: Union[str, int] = None  # error

函数注解

from typing import NoReturn

def f1() -> None:
    pass

def f2() -> NoReturn:  # 无返回值
    pass

def plus(num1: int, num2: int) -> int:
    return num1 + num2

# 带默认值
def plus_default(num1: int, num2: int = 3) -> int:
    return num1 + num2

# 容器的参数类型
def container_param(names: List[str]) -> None:
    for name in names:
        print(name)

类成员注解

class MyClass:
    attr: int
    # 带默认值的实例变量
    charge_percent: int = 100

    # 没有任何返回值应该注解为 None
    def __init__(self) -> None:
        pass

    # 忽略对 self 类型的注解
    def my_method(self, num: int, str1: str) -> str:
        return num * str1

# 支持自定义类型的注解
x: MyClass = MyClass()

结尾

OK, 差不多了,对之前的迭代器模式的代码改造一波

from typing import List, Iterable

# 抽象迭代器类
class Iterator(object):
    def hasNext(self):
        pass

    def next(self):
        pass

# 抽象聚集类
class Aggregate(object):
    def iterator(self):
        pass

class BookShelf(Aggregate):
    def __init__(self) -> None:
        self._books: List[Book] = []
        self._last: int = 0

    def getBookAt(self, index: int) -> Book:
        return self._books[index]

    def appendBook(self, book: Book) -> None:
        self._books.append(book)
        self._last = self._last + 1

    def getLength(self) -> int:
        return self._last

    def iterator(self) -> BookShelfIterator:
        return BookShelfIterator(self)

class BookShelfIterator(Iterator):
    def __init__(self, bookShelf) -> None:
        self._bookShelf: BookShelf = bookShelf
        self._index: int = 0

    def hasNext(self) -> bool:
        if self._index < self._bookShelf.getLength():
            return True
        else:
            return False

    def next(self) -> Book:
        book: Book = self._bookShelf.getBookAt(self._index)
        self._index = self._index + 1
        return book

class Book():
    def __init__(self, name) -> None:
        self._name: str = name

    def getName(self) -> str:
        return self._name

if __name__ == "__main__":
    bookShelf: BookShelf = BookShelf()
    bookShelf.appendBook(Book("A"))
    bookShelf.appendBook(Book("B"))
    bookShelf.appendBook(Book("C"))
    bookShelf.appendBook(Book("D"))

    it: Iterator = bookShelf.iterator()
    while it.hasNext():
        book: Book = it.next()
        print(book.getName())

emmm, 舒服了一丢丢/(ㄒoㄒ)/~~

参考

  • https://github.com/python/mypy
  • PyCon China 2019 成都分会场-刘知杭-静态类型的 Python, video🔗
  • PyCon China 2019 北京分会场-依云-类型检查拯救粗心开发者, video🔗
  • Type hints cheat sheet (Python 3)

本文由博客群发一文多发等运营工具平台 OpenWrite 发布


http://lihuaxi.xjx100.cn/news/2109253.html

相关文章

HTML世界之标签Ⅴ

目录 一、meter 标签 二、nav 标签 三、noscript 标签 四、object 标签 五、ol 标签 六、optgroup 标签 七、option 标签 八、output 标签 九、param 标签 十、pre 标签 十一、picture 标签 一、meter 标签 <meter> 标签定义度量衡。仅用于已知最大和最小值的…

关于继承是怎么样的?那当然是很好理解之

本文描述了关于继承的大部分知识&#xff0c;但是并不全&#xff0c;每篇博客之间的知识都有互串&#xff0c;所以需要把几篇文章合起来看&#xff0c;学会融会贯通&#xff01; 温馨提示&#xff1a;使用PC端观看&#xff0c;效果更佳&#xff01; 目录 1.继承是什么 2.什…

19.WEB渗透测试--抓包技术(下)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;18.WEB渗透测试--抓包技术&#xff08;上&#xff09;-CSDN博客 Burp含义和内容参考&…

# Maven Bom 的使用

Maven Bom 的使用 文章目录 Maven Bom 的使用概述BOM特点优点缺点 MavenMaven 安装安装步骤settingx.ml常用仓库地址Idea 使用maven常见坑 SpringBoot 项目Bom使用案例项目结构主项目 zerocode-back-servezc-dependency&#xff08;第三方jar管理&#xff09;子模块zc-serve子模…

Linux:Prometheus的源码包安装及操作(2)

环境介绍 三台centos 7系统&#xff0c;运行内存都2G 1.prometheus监控服务器&#xff1a;192.168.6.1 主机名&#xff1a;pm 2.grafana展示服务器:192.168.6.2 主机名&#xff1a;gr 3.被监控服务器&#xff1a;192.168.6.3 …

【堆、位运算、数学】算法例题

目录 十九、堆 121. 数组中的第K个最大元素 ② 122. IPO ③ 123. 查找和最小的K对数字 ② 124. 数据流的中位数 ③ 二十、位运算 125. 二进制求和 ① 126. 颠倒二进制位 ① 127. 位1的个数 ① 128. 只出现一次的数字 ① 129. 只出现一次的数字 II ② 130. 数字范围…

生成凹形曲线算法技术实践

1. 需求目标 生成曲线&#xff0c;以生成凹形曲线为例&#xff0c;如下图所示。 凹形曲线描述如下&#xff1a; 左边高点为y25&#xff08;均值&#xff09;&#xff0c;跨度4&#xff08;x[0,5)&#xff09;&#xff1b;中间最低点为y2&#xff08;均值&#xff09;&#x…

软件工程-第9章 软件工程项目管理概述

9.1 软件工程管理活动 9.2 软件规模、成本和进度估算 9.3 能力成熟度模型CMM 9.4 ISO 9000系列标准简介 9.5 CMM与ISO 9000系列标准的比较 9.6 本章小结