参考链接:https://blog.csdn.net/qq_33801641/article/details/119793104

# 一、python 类型提示概述

   python 是一种动态类型语言,这意味着我们在编写代码的时候更为自由,运行时不需要指定变量类型。但是与此同时 IDE 无法像静态类型语言那样分析代码,进而反馈响应的提示。如在下面的代码中

def split_str(s):
    strs = s.split(",")
    return strs

  由于不知道参数 s 是什么类型,所以当在 pycharm 中输入 s. 的时候不会出现 split 的语法提示。可以使用如下的程序进行类型提示,从而在程序编写时可 IDE 可以预设输入参数和输出参数类型

def split_str2(s: str) -> [str]:
    strs = s.split(",")
    return strs

  如果传入的参数类型错误,并不影响程序的运行,但是 IDE 会有 warning ,如下图所示,故类型提示更像是一个规范约束,并不是一个语法限制

# 二、常用类型提示

  • int, long, float: 整形,长整型,浮点型;
  • bool, str: 布尔型,字符串类型;
  • List, Tuple, Dict, Set: 列表,元组,字典,集合;
  • Iterable, Iterator: 可迭代类型,迭代器类型;
  • Generator: 生成器类型;
      前两行小写的不需要调用库即可使用,后三行都需要通过如 from typing import List 格式进行模块的导入。
      如下程序是较为复杂的类型提示方式
from typing import Tuple, List, Dict
# 输入第一个参数是 int 类型的数据,第二个参数是 string,第三个是 float,第四个是 bool 或 str;返回一个 Tuple 类型的数据,第一个元素是 List,第二个元素是 Tuple,第三个元素是 Dict,第四个元素可以是字符串或布尔
def add(a: int, string: str, f: float, b: bool or str) -> Tuple[List, Tuple, Dict, str or bool]:
    list1 = list(range(a))
    tup = (string, string, string)
    d = {"a": f}
    bl = b
    return list1, tup, d, bl
print(add(1, "2", 123, True))
# 输出结果
# ([0], ('2', '2', '2'), {'a': 123}, True)

⚠️⚠️⚠️在使用类型提示时一些需要注意的地方:
(1)指定类型时可以使用 listsetdicttuple ,但是不能像上述例子中一样指定里面元素的数据类型;
(2) List[T]Set[T] 只能传入一个参数类型,传入多个会报错,但是 Tuple 可以传入多个类型;
(3)在使用 Tuple[T] 的时候,元素的数量必须和类型提示的元素数量一致,如果想要像 List[T] 一样指定一个类型,可以对所有元素生效,则需要在类型后添加 ... 即可,如 Tuple[int, ...]

# 三、类型别名

  可以将复杂的类型赋予一个简单的别名,如下所示

# 别名
vector = List[float]
var: vector = [1.1, 2.2]
# 等价写法
var: List[float] = [1.1, 2.2]

# 四、自定义新类型

  可以使用 NewType(name, tp) 创建一个新类型,这个函数返回其原本的值,静态类型检查器会将新类型看作是原始类型的一个子类, tp 就是原始类型,如下程序所示

from typing import NewType
UserId = NewType('UserId', int)
def name_by_id(user_id: UserId):
    print(user_id)
name_by_id(42)  # Fails type check
name_by_id(UserId(42))  # OK
print(type(UserId(5)))
# 输出结果
# 42
# 42
# <class 'int'>

# 六、TypeVar 类型

   TypeVar 类型的源码解释(部分)如下所示

class TypeVar(_Final, _Immutable, _root=True):
    """Type variable.
    Usage::
      T = TypeVar('T')  # Can be anything
      A = TypeVar('A', str, bytes)  # Must be str or bytes

  使用方法如下所示

# 可以是任意类型
T = TypeVar('T')
def test(name: T) -> T:
    print(name)
    return name
test(11)
test("aa")
# 输出结果
# 11
# aa
# 可以是 int,也可以是 str 类型
AA = TypeVar('AA', int, str)
num1: AA = 1
num2: AA = "123"
print(num1, num2)
# 输出结果
# 1 123

# 七、任意类型(Any Type)

  一种特殊的写法是 Any ,静态类型检查器会将每种类型都是为与 Any 兼容,将 Any 是为与每种类型兼容,使用方法如下

from typing import Any
def foo(item: Any):
    # Typechecks; 'item' 可以是任意类型
    print(item)
def legacy_parser(text):
    ...
    return data
# 上述写法等价于下述写法
# 所有没有返回类型或参数类型的函数将隐式默认使用 Any
def legacy_parser(text: Any) -> Any:
    ...
    return data

# 八、联合类型(Union)

  联合类型, Union[int, str] 表示既可以是 int ,也可以是 str ,程序解释如下

vars: Union[int, str]
# 等价于
vars: [int or str]
vars: Union[int]
# 等价于
vars: int

# 九、参数可 None 类型(Optional)

  使用 Optional 是为了让 IDE 识别到该参数有一个类型提示,可以传指定的类型和 None,即参数是可选单非必要的, Optional[int] 等价于 Union[int, None] ,使用案例如下

def foo_func(arg: Optional[int] = None):
    print(arg)
foo_func()
foo_func(1)
# 输出结果
# None
# 1
更新于 阅读次数