3.10【2021-10】
🌟新增
1、语法 match ... case ()
我还是更喜欢较 switch 语法,一个可读性非常好的语法,在js和java用的超级舒服,终于python也有了
传统写法:
def http_error(status:int) -> str:
if status == 400:
return "Bad request"
elif status == 404:
return "Not found"
elif status == 418:
return "I'm a teapot"
else:
return "Something's wrong with the internet"
基础语法:
def http_res(status:int) -> str:
match status:
case 301 | 302 | 303:
return "3*"
case 400 | 404 | 418:
return "Not allowed"
case _:
return "Something's wrong with the internet"
def http_error(status:int) -> str:
match status:
case 400:
return "Bad request"
case 404:
return "Not found"
case 418:
return "I'm a teapot"
case _:
return "Something's wrong with the internet"
case _:
类似于其它语言中的 default ,当其他条件都不符合就执行这行。
应用场景:
匹配数组
command = "save 1.txt"
# 试着把command改成 list / copy 1.txt 2.txt 看看效果
match command.split(" "):
case ["list"]:
print("列出文件~")
case ["save", file_name]:
print(f"保存文件到 {file_name}")
case ["copy", source, target]:
print(f"拷贝 {source} -> {target}")
匹配对象
class Person():
pass
class Student(Person):
def __init__(self, id: int) -> None:
self.id = id
class Teacher(Person):
def __init__(self, name: str) -> None:
self.name = name
a = Student(1)
# a = Student(2)
# a = Teacher("FunnySaltyFish")
match a:
case Student(id = 2):
print(f"这是位学生,且id正好是2")
case Student():
print(f"这是学生,id为{a.id}")
case Teacher():
print(f"这是老师, 姓名为{a.name}")
匹配字典
d = {
"name" : "李四", # 张三
"age" : 18,
"hobby" : "阅读"
}
match d:
case {"name":"张三", **args}:
# **收集其他参数
print("这是张三", args) # 这是张三 {'age': 18, 'hobby': '阅读'}
case {"name" : name , "age" : age, "hobby": hobby}:
print(f"我叫{name}, 今年{age}岁, 喜欢{hobby}") #我叫李四,今年18岁,喜欢阅读
配合 * 通配符
import sys
match sys.argv[1:]:
case ["quit"]:
print("exit")
case ["create", user]: # 创建单个用户
print("create", user)
case ["create", *users]: # 批量创建多个用户
for user in users:
print("create", user)
case _:
print("Sorry, I couldn't understand the argv")
2、新的联合类型操作符 “|”
在之前版本中,对于函数参数如果希望类型支持多种,例如同时支持int和float,需要用Union:
from typing import Union
联合操作符 “|”:
- 类型定义
# 3.9
a: Union[int, str] = 1
# 3.10
a: str | int = 1
# 3.9
typing.List[typing.Union[str, int]]
# 3.10
typing.List[str | int]
list[int|sr]
# 3.9
typing.Dict[str, typing.Union[int, float]]
# 3.10
typing.Dict[str, int | float]
dict[str, int | float]
- 函数定义
# 3.10
def square(number: int | float) -> int | float:
return number ** 2
# 3.9
def foo(number: Union[ int, float]) -> Union[int, float]:
return number ** 2
# 3.10
def f(list: List[int | str], param: int | None) -> float | str:
pass
# 3.9
def f(list: List[Union[int, str]], param: Optional[int]) -> Union[float, str]
pass
- 类型判断
isinstance
和issubclass
# 3.10
>>> isinstance(1, int | str)
True
# 3.9
>>> isinstance(1, (int,float))
True
# 3.9
issubclass(str, (str,int))
# 3.10
issubclass(str, str|int)
3、TypeAlias 显示标注类型别名
新的方式:使用 TypeAlias表明这是个别名
from typing import TypeAlias
x : TypeAlias = int
def plus_int(a:x,b:x) -> x:
return a+b
✴优化
1、更精准的错误提示
expected = {9: 1, 18: 2, 19: 2, 27: 3, 28: 3, 29: 3, 36: 4, 37: 4,
38: 4, 39: 4, 45: 5, 46: 5, 47: 5, 48: 5, 49: 5, 54: 6,
some_other_code = foo()
比如这段代码如果你不小心漏掉一个右花括号,运行代码时,在之前的版本中直接提示语法错误:
File "example.py", line 3
some_other_code = foo()
^
SyntaxError: invalid syntax
不仔细检查代码你还真的没法一眼看出来到底哪里语法错误。而在python3.10中,提示变得非常友好而且具体, 直接告诉你"{"
没有关闭,这样定位错误就很快了。
File "example.py", line 1
expected = {9: 1, 18: 2, 19: 2, 27: 3, 28: 3, 29: 3, 36: 4, 37: 4,
^
SyntaxError: '{' was never closed
类似地,还有推导式中如果忘记加圆括号时,之前一言不合直接提示语法错误
>>> {x,y for x,y in zip('abcd', '1234')}
File "<stdin>", line 1
{x,y for x,y in zip('abcd', '1234')}
^
SyntaxError: invalid syntax
而现在会告诉你,是不是忘记加圆括号了。
>>> {x,y for x,y in zip('abcd', '1234')}
File "<stdin>", line 1
{x,y for x,y in zip('abcd', '1234')}
^
SyntaxError: did you forget parentheses around the comprehension target?
非常人性化
2、带括号的上下文管理器 with()
以往我们需要同时执行多个上下文时:
传统写法:
with open("xxx.py", mode="w") as f1, open("yyy.py", mode="w") as f2:
pass
# 或者
with open("xxx.py", mode="w") as f1, \
open("yyy.py", mode="w") as f2:
pass
现在:
# 直接使用括号+逗号即可
with ( open("xxx.py", mode="w") as f1, open("yyy.py", mode="w") as f2 ):
pass
# 或者
with (
open("xxx.py", mode="w") as f1,
open("yyy.py", mode="w") as f2,
open("yyy.py", mode="w") as f3,
open("yyy.py", mode="w") as f4
):
pass
import pathlib
p = pathlib.Path()
p1 = p/"text1.txt" # 内容:文本1的内容
p2 = p/"text2.txt" # 内容:文本2的内容
with(
p1.open(encoding="utf-8") as f1,
p2.open(encoding="utf-8") as f2
):
print(f1.read(), f2.read(), sep="\n")
# 文本1的内容
# 文本2的内容
3、zip 可选严格模式
zip新增可选参数strict
, 当该选项为True时,传入zip的两个可迭代项长度必须相等,否则将抛出 ValueError
names = ["a","b","c","d"]
numbers = [1,2,3]
z = zip(names,numbers)
for each in z:
print(each)
# ('a', 1)
# ('b', 2)
# ('c', 3)
- 设置strict为True
# ...
z = zip(names,numbers,strict=True)
# ...
d:\projects\python\learn\Py310探索.py in <module>
3 numbers = [1,2,3]
4 z = zip(names,numbers,strict=True)
----> 5 for each in z:
6 print(each)
ValueError: zip() argument 2 is shorter than argument 1