python是动态语言,不用为参数和变量声明类型,但是可以用泛型来描述参数变量的类型来提高代码的可读性(泛型或泛型变量或实际类型都可以用来描述这个参数或变量的类型)
# 不使用类型提示
def func(a,b):
return a+b
func('1','1') # '11'
func(1,1) # 2
func('1',1) # 未使用类型提示,代码编辑时不会报错,代码执行时会报错
# 使用类型提示
from typing import overload
@overload
def func(a: int, b: int): pass
@overload
def func(a: str, b: str): pass
def func(a, b):
return a + b
func(1, '1') # 使用类型提示,在代码编辑时就会报错,可以在代码执行前预防可能出现的问题
type hint
提示类型并不是可用类型,如typing.List并不是list的子类,typing.List只是一个type hint,对a参数指定一个type hint,这个type hint会被设置为func方法a入参的type hint属性,执行代码不会其任何作用,但是执行代码过程中可以获取到这个type hint属性,并使用它做一些处理
常见type hint
- List是list的泛型(泛型:表示某种类型)
- Tuple是tuple的泛型
- NamedTuple是collections.namedtupe的泛型
- Dict是dict的泛型
- Mapping是collections.Mapping的泛型
- Set是set的泛型
- Sequence是collection.Sequence的泛型/tuple+list的泛型
- NoReturn是无返回的泛型
- Any是任意类型的泛型
- TypeVar,可以创建泛型变量,就是传什么泛型就是什么泛型(
T = TypeVar('T')
) - NewType,一个新的类型(不是泛型),
List=NewType('List', list)``Person=NewType('Person', str)
- Callable是可调用类型的泛型
- Union是联合类型
- Optional是可为空的联合类型
- Generator是一个生成器类型
typing.Generic&typing.TypeVar
from typing import Generic, TypeVar, List
T = TypeVar('T') # 定义一个泛型变量, 接收什么泛型这个泛型变量就是什么泛型
class Base(Generic[T]): # 定义一个Base,Base会用到一个泛型T
def set_t(self, t: T):
self.t = T
def get_t(self) -> T:
return self.t
class BaseList(Base[List]):# 继承Base类型并进一步定义T,让T=List, Base[List]就和Dict[str, Any]一样的道理,都是List/str/any描述Base或List类内部参数类型
pass
base_list = BaseList()
base_list.set_t(t='') # 这里入参t需要传T=>List类型,这里传str,idea竟然没有检查到类型
base_list.get_t().append() # 这里get_t返回的是T=>List类型,idea会提示List的方法
目前idea对部分type hint不支持,但是使用type hint代码的可读性更高
每个类型都有自己的泛型,如List,Tuple,实际类型list/tuple等也可以做类型提示
Union/Optional定义可选泛型, Union[int,str], 描述参数可以选择传int,也可以选择传str
TypeVar定义一个可变的泛型变量,泛型变量可以接收泛型/实际类型,T=TypeVar('T', bound=xxx)
Generic定义一组泛型,Base(Generic[T]) -> BaseChild(Base[List])