python3 类型标注_详解python3类型注释annotations实用案例

1、类型注解简介

Python是一种动态类型化的语言,不会强制使用类型提示,但为了更明确形参类型,自python3.5开始,PEP484为python引入了类型注解(type hints)

示例如下:

c80a7d2d33c65887954bc47a6f62ef4c.png

2、常见的数据类型

int,long,float: 整型,长整形,浮点型

bool,str: 布尔型,字符串类型

List, Tuple, Dict, Set: 列表,元组,字典, 集合

Iterable,Iterator: 可迭代类型,迭代器类型

Generator:生成器类型

Sequence: 序列

3、基本的类型指定

def test(a: int, b: str) -> str:

print(a, b)

return 200

if __name__ == '__main__':

test('test', 'abc')

函数test,a:int 指定了输入参数a为int类型,b:str b为str类型,-> str 返回值为srt类型。可以看到,在方法中,我们最终返回了一个int,此时pycharm就会有警告;

当调用这个方法时,参数a 输入的是字符串,此时也会有警告;

but…,pycharm这玩意儿 只是提出了警告,但实际上运行是不会报错,毕竟python的本质还是动态语言。

98e5b4a18ca0ad4ba3e88b214673a0ef.png

4、复杂的类型指定

指定列表

from typing import List

Vector = List[float]

def scale(scalar: float, vector: Vector) -> Vector:

return [scalar * num for num in vector]

# type checks; a list of floats qualifies as a Vector.

new_vector = scale(2.0, [1.0, -4.2, 5.4])

print(new_vector)

指定 字典、元组 类型

from typing import Dict, Tuple, Sequence

ConnectionOptions = Dict[str, str]

Address = Tuple[str, int]

Server = Tuple[Address, ConnectionOptions]

def broadcast_message(message: str, servers: Sequence[Server]) -> None:

print(message)

print(servers)

# The static type checker will treat the previous type signature as

# being exactly equivalent to this one.

if __name__ == '__main__':

broadcast_message('OK', [(('127.0.0.1', 8080), {"method": "GET"})])

ef4387ae487264dca55f33012e290da9.png

这里需要注意,元组这个类型是比较特殊的,因为它是不可变的。

所以,当我们指定Tuple[str, str]时,就只能传入长度为2,并且元组中的所有元素都是str类型

5、创建变量时的类型指定

对于常量或者变量添加注释

from typing import NamedTuple

class Employee(NamedTuple):

name: str

id: int = 3

employee = Employee('Guido')

# assert employee.id == 3 # 当类型一致时,不会输出内容,反之报错

assert employee.id == '3' # 当类型一致时,不会输出内容,反之报错

# AssertionError

指定一个变量odd,显式的声明了它应该是整数列表。如果使用mypy来执行这个脚本,将不会收到任何提示输出,因为已经正确地传递了期望的参数去执行所有操作。

from typing import List

def odd_numbers(numbers: List) -> List:

odd: List[int] = []

for number in numbers:

if number % 2:

odd.append(number)

return odd

if __name__ == '__main__':

numbers = list(range(10))

print(odd_numbers(numbers))

mypy 安装

pip install mypy

执行 mypy file,正常情况下不会报错

C:\Users\Sunny_Future\AppData\Roaming\Python\Python36\Scripts\mypy.exe tests.py

# 指定 环境变量或者 linux 下可以直接执行 mypy

# mypy tests.pySuccess: no issues found in 1 source file

0cbfeeeb42585ee9ec5f3d028914a5d0.png

接下来,尝试更改一下代码,试图去添加整形之外的其他类型内容!那么执行则会检查报错

from typing import List

def odd_numbers(numbers: List) -> List:

odd: List[int] = []

for number in numbers:

if number % 2:

odd.append(number)

odd.append('foo')

return odd

if __name__ == '__main__':

numbers = list(range(10))

print(odd_numbers(numbers))

代码中添加一个行新代码,将一个字符串foo附加到整数列表中。现在,如果我们针对这个版本的代码来运行mypy

C:\Users\Sunny_Future\AppData\Roaming\Python\Python36\Scripts\mypy.exe tests.py

403c4f9f80f0403243d7763aa0067d41.png

tests.py:114: error: Argument 1 to “append” of “list” has incompatible type “str”; expected “int”

Found 1 error in 1 file (checked 1 source file)

6、 泛型指定

from typing import Sequence, TypeVar, Union

T = TypeVar('T') # Declare type variable

def first(l: Sequence[T]) -> T: # Generic function

return l[0]

T = TypeVar('T') # Can be anything

A = TypeVar('A', str, bytes) # Must be str or bytes

A = Union[str, None] # Must be str or None

7、再次重申

在Python 3.5中,你需要做变量声明,但是必须将声明放在注释中:

# Python 3.6

odd: List[int] = []

# Python 3.5

odd = [] # type: List[int]

如果使用Python 3.5的变量注释语法,mypy仍将正确标记该错误。你必须在 #井号之后指定type:。如果你删除它,那么它就不再是变量注释了。基本上PEP 526增加的所有内容都为了使语言更加统一。

8、不足之处

虽然指定了 List[int] 即由 int 组成的列表,但是,实际中,只要这个列表中存在 int(其他的可以为任何类型),pycharm就不会出现警告,使用 mypy 才能检测出警告!

from typing import List

def test(b: List[int]) -> str:

print(b)

return 'test'

if __name__ == '__main__':

test([1, 'a'])

pycharm 并没有检测出类型错误,没有告警

6f8ea10a4391102b84111b61d51255a9.pngmypy

工具 检测到 类型异常,并进行了报错

00f3fdd195e32864ca1874574b1ed4a8.png

9、demo

# py2 引用

from__future__import annotations

class Starship:

captain: str = 'Picard'

damage: int

stats: ClassVar[Dict[str, int]] = {}

def __init__(self, damage: int, captain: str = None):

self.damage = damage

if captain:

self.captain = captain # Else keep the default

def hit(self):

Starship.stats['hits'] = Starship.stats.get('hits', 0) + 1

enterprise_d = Starship(3000)

enterprise_d.stats = {} # Flagged as error by a type checker

Starship.stats = {} # This is OK

from typing import Dict

class Player:

...

players: Dict[str, Player]

__points: int

print(__annotations__)

# prints: {'players': typing.Dict[str, __main__.Player],

# '_Player__points': }

class C:

__annotations__ = 42

x: int = 5 # raises TypeError

到此这篇关于详解python3类型注释annotations实用案例的文章就介绍到这了,更多相关python3类型注释annotations内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值