Dawn's Blogs

分享技术 记录成长

0%

Python杂谈 (2) 海象运算符和类型声明

海象运算符

从 Python 3.8 开始,加入了海象运算符 :=,语法格式是 variable_name := expression

用法

用于 if-else 条件表达式中

1
2
if a := 5 > 1:
print("do sth")

用于 while 循环

1
2
3
4
5
6
7
8
9
10
# 常规写法
n = 3
while n:
    print('do sth!')
    n -= 1

# 升级写法
n = 3
while (n := n - 1) + 1
    print('do sth!')

加 1 是因为在循环条件判断之前,n 已经减 1 了。

读取文件

1
2
3
fp = open("test.txt""r")
while line := fp.readline():
    print(line)

类型声明

Python 3.6 开始,Python 加入类型声明,声明语法为 variable_name: type

需要注意的是,类型声明只是起到提示的作用,在实际运行过程中,若实际类型与声明类型不符也不会报错。

复杂类型声明

若想对list、dict、tuple的内容做类型声明,可以用 typing 包:

1
2
3
4
5
6
7
8
9
10
11
12
from typing import List, Dict, Tuple

# 声明列表
a_list: List[str]

# 声明字典
# key为str,value为int
b_dict: Dict[str, int]

# 声明元组
# value为float,个数为任意(或者可以指明个数)
c_tuple: Tuple[float, ...]

函数类型声明

也可以对函数的参数返回值进行类型的声明:

1
2
def add(a: int, b: int) -> int:
return a+b

函数类型检查

可以通过装饰器,对函数的类型进行检查:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from typing import get_type_hints
from functools import wraps
from inspect import getfullargspec

# 类型检查
def validate_input(obj, **kwargs):
hints = get_type_hints(obj) # 获取参数、返回值;hints为字典
for param_name, param_type in hints.items():
if param_name == 'return':
# 不检查返回值
continue
if not isinstance(kwargs[param_name], param_type not issubclass(type(kwargs[param_name]), param_type):
# 类型不匹配 and 没有继承关系
raise TypeError(f'参数: {param_name} 应该是: {param_type}或子类')

# 声明一个装饰器
def type_check(decorator):
@wraps(decorator)
def wrapped_decorator(*args, **kwargs):
func_args = getfullargspec(decorator)[0] # 提取传入参数
kwargs.update(dict(zip(func_args, args))) # 将数据更新到kwargs中
validate_input(decorator, **kwargs) # 验证参数
return decorator(**kwargs) # 调用被装饰方法

return wrapped_decorator

@type_check 会对函数参数的类型进行检查,若类型错误则会抛出 TypeError

1
2
3
@type_check
def add(a: int, b: int) -> int:
return a+b