python泛型

文章目录

    • 泛型
      • 变量类型设置
      • 类型提示的元组打包
      • 变量类型提示-元组解包
      • 函数参数类型提示
      • 常用类型
      • 变量别名
      • NewType
      • Callable
      • TypeVar泛型
      • Any Type
      • Union
      • Optional

泛型

参考资料:[Python - typing 模块 —— TypeVar 泛型 - 小菠萝测试笔记 - 博客园 (cnblogs.com)](Python - typing 模块 —— TypeVar 泛型 - 小菠萝测试笔记 - 博客园 (cnblogs.com))

python是一种动态类型语言,运行时不需要指定变量类型

同时也存在无法及时给出语法提示或类型出错等问题

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

'''
在传递s参数时,由于无法知道s类型
所以无法在编程时给出语法提示
'''

为了解决上述问题,Python3.5、3.6新增两个特性PEP 484 和PEP 526

  • PEP 484:函数参数提示
  • PEP 526:变量提示

变量类型设置

from typing import List, ClassVar, Dict

# int 变量,默认为0
num : int = 0

# bool 变量,默认值为True
bool_var : bool = True

# 字典变量,默认为空
dict_var : Dict = {}

# 列表变量,且列表元素为 int
primes : List[int] = []

class Starship:
    # 类变量,字典类型,键 - 字符串,值 - 整型
    '''
    ClassVar是typing模块的一个特殊类
    它想静态类型检查器指示不应该在类实例设置此变量
    '''
    stats : ClassVar[Dict[str,int]] = {}
    # 实例变量
    num : int

当你传入参数与设置的参数类型不一样时,只会warning,而不会报错

类型提示的元组打包

# 正常的元组打包
a = 1, 2, 3

# 加上类型提示的元组打包
t: Tuple[int, ...] = (1, 2, 3)
print(t)

t = 1, 2, 3
print(t)

# py3.8+ 才有的写法
# 不加...会有warning提示
t: Tuple[int, ...] = 1, 2, 3
print(t)

t = 1, 2, 3
print(t)


# 输出结果
(1, 2, 3)
(1, 2, 3)
(1, 2, 3)
(1, 2, 3)

变量类型提示-元组解包

# 正常元组解包
message = (1, 2, 3)
a, b, c = message
print(a, b, c)  # 输出 1 2 3

# 加上类型提示的元组解包
header: str
kind: int
body: Optional[List[str]]

# 不会 warning 的栗子
header, kind, body = ("str", 123, ["1", "2", "3"])

# 会提示 warning 的栗子
header, kind, body = (123, 123, ["1", "2", "3"])

函数参数类型提示

# 参数 name 类型提示 str,而函数返回值类型提示也是 str
def greeting(name: str) -> str:
    return 'Hello ' + name

常用类型

  • int,float:整型,浮点型
  • bool,str:布尔型,字符串类型
  • List,Tuple,Dict,Set:列表,元组,字典,集合
  • Iterable,Iterator:可迭代类型,迭代器类型
  • Generator:生成器类型

除了第一和第二点,其他都要import typing模块进行导入

指定类型的时候用list、set、dict、tuple也是可以的,但是不能指定里面的元素类型

且List[T]、Set[T]只能传一个类型,传多个会报错

Dict[T,T]第一个参数指定键的类型,第二个参数指定值得类型

Tuple[T] 指定一个类型的时候,仅针对同一个索引下的元素类型

如果想向List[T]一样指定全部的类型,可以Tuple[T,…]

变量别名

可以将复杂一点类型给个别名,这样好用一点

# 别名
vector = List[float]

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

NewType

可以自定义一个新类型:

  • 主要用于类型检查
  • NewType(name,tp)返回一个函数,这个函数返回其原本的值
  • 静态类型检查器会将新类型看做原始类型的一个子类
  • tp就是原始类型
# NewType
from typing import NewType

UserId = NewType('UserId', int)


def name_by_id(user_id: UserId) -> str:
    print(user_id)


UserId('user')  # Fails type check
num = UserId(5)  # type: int

name_by_id(42)  # Fails type check
name_by_id(UserId(42))  # OK

print(type(UserId(5)))

# 输出结果
42
42
<class 'int'>

# UserId不等于int类型,编译器检查会Warning
# 使用 UserId 类型做算术运算,得到的是 int 类型数据

Callable

内置函数,返回一个变量是否可以回调

或者typing库函数

from typing import Callable
def f():
    return 1

print(callable(f))
print(isinstance(f, Callable))


# True
# True
# 语法
Callable type; Callable[[int], str] is a function of (int) -> str.

# 
第一个类型[int]代表参数类型
第二个类型[str]代表返回值类型

from typing import Callable

def print_name(name: str):
    print(name)


# Callable 作为函数参数使用,其实只是做一个类型检查的作用,检查传入的参数值 get_func 是否为可调用对象
# Callable  作为函数返回值使用,其实只是做一个类型检查的作用,看看返回值是否为可调用对象
def get_name(get_func: Callable[[str], None]):
    return get_func


vars = get_name(print_name)
vars("test")


TypeVar泛型

from typing import TypeVar

# 设置T为任意类型
T = TypeVar('T')
# 设置可以是int类型也可以是str类型
AA = TypeVar('AA',int, str)

Any Type

  • 特殊类型Any
  • 静态类型检查器会将每种类型都视为与Any兼容
from typing import Any


def foo(item: Any) -> int:
    # Typechecks; 'item' 可以是任意类型
    print(item)
    return 

# 隐式使用 Any
def legacy_parser(text):
    ...
    return data

Union

联合类型

Union[int,str] 表示既可以是int,也可以是str

from typing import Union

var : Union[int,str]

# union 嵌套 union 会自动解包
Union[Union[int, str], float] == Union[int, str, float]

Optional

可选类型

  • 不过 Optional 和默认参数其实没啥实质上的区别,只是写法不同
  • 使用 Optional 是为了让 IDE 识别到该参数有一个类型提示,可以传指定的类型和 None,且参数是可选非必传的
  • Optional[int] 等价于 Union[int, None]
  • 意味着:既可以传指定的类型 int,也可以传 None
  • Optional[] 里面只能写一个数据类型
def foo_func(arg: Optional[int] = None):
    print(arg)


foo_func()
foo_func(1)


# 输出结果
None
1

你可能感兴趣的:(python,python,开发语言)