类型提示
# VsCode安装Flake8
# 介绍
- Flake8是Python的静态代码检查工具
# 安装
- 命令行安装
pip3 install flake8
- vscode配置
# setting.json文件中
{
... ...
# 开启flake8工具
"python.linting.flake8Enabled": true,
# 关闭pylint工具
"python.linting.pylintEnabled": false
... ...
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# Python类型提示介绍
# 类型提示出现原因
- Python是一种动态类型语言,这意味着我们在编写代码的时候更为自由,运行时不需要指定变量类型
- 但是与此同时IDE无法像静态类型语言那样分析代码,及时给我们相应的提示,比如字符串的
split
方法 - 由于不知道参数
s
是什么类型,所以当你敲s.
的时候不会出现split
方法的语法提示 - 例如
def split_str(s):
strs = s.split(",")
1
2
2
# 类型提示作用
- Python3.5、3.6新增了两个特性
PEP 484
和PEP 526
,来帮助IDE为我们提供更智能的提示 - 这些新特性不会影响语言本身,只是增加一点提示声明而已
# 类型提示分类
- 变量提示:
PEP 526
特性中的 - 函数参数提示:
PEP 484
特性中的
# 常用提示类型
int
:整数类型long
:长整类型float
:浮点类型bool
:布尔类型str
:字符串类型- =========以下类型需要从
typing模块
中导入========= List
:列表类型Tuple
:元组类型Dict
:字典类型Set
:集合类型Iterable
:可迭代类型Iterator
:迭代器类型Generator
:生成器类型
# 变量类型提示
# 介绍
- 没有使用类型提示时,想说明变量的数据类型只能通过注释,例如:
primes = [] # primes is a list
- 而使用了变量类型提示,就可以直接声明提示的变量类型
- 如果变量标注了类型,传错了也不会报错,但是会有warning,这是IDE的智能语法提示
- 所以类型提示仅仅只是一个规范约束,并不是一个语法限制
# 使用方法
- 类型提示声明
变量名: 提示的类型 = 值
变量名: 类型1 or 类型2 = 值
- 也可以同时声明两个提示的类型,表示既可以是
[类型1]
也可以是[类型2]
- 也可以同时声明两个提示的类型,表示既可以是
- 列表类型声明
primes: List[int] = []
- 声明变量是列表类型、且元素为int类型
- int类型声明
num: int = 0
- 声明变量是int类型
- bool类型声明
bool_var: bool = True
- 声明变量是bool类型
- 字典类型声明
dict_var: Dict = {}
- 声明变量是字典类型
- 类变量声明
- 声明类变量是字典类型,且键是字符串类型,值是int类型
class Starship:
# ClassVar 是 typing 模块的一个特殊类,它向静态类型检查器指示不应在类实例上设置此变量
stats: ClassVar[Dict[str, int]] = {}
1
2
3
2
3
- 实例变量声明
class Starship:
# 实例变量,有默认值
name: str = 'Picard'
# 实例变量,没有默认值
age: int
1
2
3
4
5
2
3
4
5
- 元组打包类型声明
- 声明变量是列表类型、且元素为int类型,另外如果不加...的话,元组打包的时候,可能会有一个warning提示
t: Tuple[int, ...] = 1, 2, 3
- 元组解包类型声明
# 先声明解包时会赋值的变量的类型
name: str
age: int
# 解包
name, age = ("alis", 18)
1
2
3
4
5
2
3
4
5
# 注意
- 有些类型需要先从
typeing模块
导入- 从模块中导入类型:
from typing import List, Dict...
List
:列表类型Tuple
:元组类型Dict
:字典类型Set
:集合类型Iterable
:可迭代类型Iterator
:迭代器类型Generator
:生成器类型
- 从模块中导入类型:
List[T]
和Set[T]
中只能传一个类型,传多个的话,IDE不会报错,但运行时会报错- 例如:
List[int, str]
- 运行会报错
List[int]
- 运行不会报错
- 例如:
Tuple[T]
中可以传多个类型,运行不会报错- 例如:
Tuple[int, str]
- 例如:
Tuple[T]
如果值的数量与类型的数量对不上,则IDE可能会警告,但可以写...
来表示值可能有多个- 注意:写...时,类型只能指定一个,否则会语法错误
- 例如:
Tuple[int, int, int] = (1, 2, 3, 4)
- IDE有警告
Tuple[int, int, int] = (1, 2, 3)
- IDE没有警告
Tuple[int, ...] = (1, 2, 3)
- IDE没有警告
Tuple[int, str, ...] = (1, 2, 3)
- 语法错误
# 函数参数类型提示
# 介绍
- 不仅提供了函数参数列表的类型提示,也提供了函数返回的类型提示,且使用方法类似
# 使用方法
def 函数名(变量名: 类型) -> 返回值类型: ... ...
- 例如:
def hello(name: str) -> str:
return 'Hello ' + name
def greeting(name: str, obj: Dict[str, List[int]]) -> None:
print(name, obj)
1
2
3
4
5
2
3
4
5
# 类型别名
# 介绍
- 可以给复杂的类型取个别名,调用会更方便
# 使用方法
- 定义
别名 = 类型
- 例如:
user_type = Tuple[Dict[str, str], ...]
- 引用
变量名: 类型别名 = 值
- 例如:
user_obj = ({"name": "alis"})
# 使用例子
ConnectionOptions = Dict[str, str]
Address = Tuple[str, int]
Server = Tuple[Address, ConnectionOptions]
def broadcast_message(message: str, servers: Server) -> None:
print(message, servers)
message = "发送服务器消息"
servers = (("127.0.0.1", 127), {"name": "服务器1"})
broadcast_message(message, servers)
发送服务器消息 (('127.0.0.1', 127), {'name': '服务器1'})
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# Callable类型
# 介绍
- Callable表示是可调用的对象类型
- Callable类型可以用于函数参数的类型声明、判断对象是否可调用等
# 使用方法
- 导入模块
from typing import Callable
- Callable作为函数参数类型
Callable[[形参类型], 返回值类型]
- 例如:
Callable[[str], None]
- 例如:
- 使用例子
def hello() -> Callable[[str], None]:
def iam(name):
print("i'am " + name)
return iam
a = hello()
a("alis")
1
2
3
4
5
6
2
3
4
5
6
# isinstance方法
isinstance(对象, Callable)
- 查看对象是否可调用,可通过isinstance来判断
- 函数或类是可调用的,会返回True
- 而变量不是可调用对象,会返回False
# Any类型
# 介绍
Any
是一种特殊的类型,可以将其当做任意类型- 静态类型检查器会将每种类型都视为与Any兼容,将Any视为与每种类型兼容
- 如果不声明类型,默认就是Any类型,但声明可能会使语义更明确
- 例如:
"a = 1" 同等于 "a: Any = 1"
- 例如:
# 使用方法
from typing import Any
变量名: Any = 值
1
2
2
# 使用例子
from typing import Any
def hello(name: Any) -> None:
print("hello " + name)
# 实际上同等于
def hello(name) -> None:
print("hello " + name)
1
2
3
4
5
6
2
3
4
5
6
# Union类型
# 介绍
- Union可以用于声明多种类型,以表示值可以为多种类型
- 特点
- 声明单个类型同等于该类型
Union[int] == int
- 重复的类型参数会自动忽略掉
Union[int, str, int] == Union[int, str]
- 且会自动忽略类型参数顺序
Union[int, str] == Union[str, int]
- union 嵌套 union 会自动解包
Union[Union[int, str], float] == Union[int, str, float]
- 声明单个类型同等于该类型
# 使用方法
from typing import Union
Union[类型1, 类型2...]
# 使用例子
from typing import Union
def hello(name: Union[int, str]) -> None:
print("hello " + name)
1
2
3
2
3
# Optional可选类型
# 介绍
- 声明Optional类型可以表示该参数为可选参数
- Optional和默认参数其实没啥实质上的区别,只是写法不同
- 使用Optional只是为了让IDE识别该参数时有一个类型提示,表示该参数可选
# 使用方法
from typing import Optional
Optional[类型]
- 注意:
Optional[T]
里面只能写一个类型
- 注意:
# 使用例子
def foo_func(name: Optional[str] = "alis"):
print(name)
# 实际同等于
def foo_func(name: str = "alis"):
print(name)
1
2
3
4
5
2
3
4
5
# 注意
- "Optional[类型]" 等价于 "Union[类型, None]"
- 表示既可以传指定的类型,也可以传None
# NewType新类型
# 介绍
- 除了使用内置的类型,我们也可以自己定义新类型,用作类型提示
NewType
主要用于类型检查,静态类型检查器会将新类型看作是原始类型的一个子类
# 使用方法
from typing import NewType
- 需要先导入NewType类
NewType(name, tp)
- 调用该函数会返回一个函数,这个函数返回其原本的值
- tp 就是原始类型
# 使用例子
from typing import NewType
UserId = NewType('UserId', int)
UserId('user')
UserId(1000)
def name_by_id(user_id: UserId):
print(user_id)
name_by_id(1000)
name_by_id(UserId(1000))
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# TypeVar泛类型
# 介绍
- TypeVar和NewType类似,只不过可以指定多个类型
# 使用方法
from typing import TypeVar
类型名 = TypeVar("类型名")
- 类型名参数后面没有跟任何类型,则表示任意类型
类型名 = TypeVar("类型名", 类型1, 类型2...)
- 类型名参数后面跟的类型,是该类型允许的类型
# 使用例子
# 表示AA类型可以是int类型或str类型
AA = TypeVar('AA', int, str)
test1: AA = 1
test2: AA = "1"
1
2
3
4
2
3
4
# 注意
- 类型的变量名必须和参数定义的类型名一致