概述
- python3.6新增特性
- 新增f字符串
- 数字中的下划线
- 异步生成器
- 异步推导式
- 新增方法:`__init_subclass__`
- 新增方法:`__set_name__`
- 路径支持使用对象
- 路径默认编码改为utf-8
- Windows控制台编码改为utf-8
- 新的dict实现
- 新增secrets模块
- python3.7新增特性
- 新增dataclass
- 新增importlib.resources
- python3.8
- :=
- 函数参数新增`/`语法
- f字符串新增=语法
- 具有外部数据缓冲区的 pickle 协议 5
- 新增importlib.metadata模块
- python3.9
- 字典之间新增`|`和`|=`运算符
- 字符串新增两个方法
python3.6新增特性
https://docs.python.org/zh-cn/3.6/whatsnew/3.6.html
新增f字符串
用法和format基本是一样的
>>> name = "Fred"
>>> f"He said his name is {name}."
'He said his name is Fred.'
>>> "He said his name is {name}.".foramt(name=name)
'He said his name is Fred.'
>>> width = 10
>>> precision = 4
>>> value = decimal.Decimal("12.34567")
>>> f"result: {value:{width}.{precision}}" # nested fields
'result: 12.35'
>>> "result: {value:{width}.{precision}}".format(width=width,precision=precision, value=value)
'result: 12.35'
只是把format写法精简了,更多的格式化语法可以看: https://docs.python.org/zh-cn/3.6/library/string.html#formatspec
数字中的下划线
>>> 1_0_0_0
1000
>>> 1_000_000_000_000_000
1000000000000000
>>> 0x_FF_FF_FF_FF
4294967295
允许在数字之间添加下划线让代码更好看。不能再开头和结尾出现下划线,而且不能连续出现两个下划线
另外format语法也支持_
>>> '{:_}'.format(1000000)
'1_000_000'
>>> '{:_x}'.format(0xFFFFFFFF)
'ffff_ffff'
异步生成器
允许在异步函数内同时出现yield和await,也就是可以实现异步生成器
async def ticker(delay, to):
"""Yield numbers from 0 to *to* every *delay* seconds."""
for i in range(to):
yield i
await asyncio.sleep(delay)
异步推导式
result = [i async for i in aiter() if i % 2]
result = [await fun() for fun in funcs if await condition()]
这种语法我感觉用不上
新增方法:__init_subclass__
没看懂,略
新增方法:__set_name__
没看懂,略
路径支持使用对象
在之前的版本里,传入一个路径基本都是使用字符串,现在可以使用pathlib.Path("/root/1.txt"))
,它实现了__fspath__来表示实际的路径
>>> import pathlib
>>> with open(pathlib.Path("README")) as f:
... contents = f.read()
...
>>> import os.path
>>> os.path.splitext(pathlib.Path("some_file.txt"))
('some_file', '.txt')
>>> os.path.join("/a/b", pathlib.Path("c"))
'/a/b/c'
>>> import os
>>> os.fspath(pathlib.Path("some_file.txt"))
'some_file.txt'
这篇文章详细的介绍了:https://zhuanlan.zhihu.com/p/87940289
路径默认编码改为utf-8
python3.5是mbcs。
>>> import sys
>>> sys.getfilesystemencoding()
'mbcs'
正常来说是没有影响的,因为操作路径一般给的都是字符串而不是字符,总不会有人这么写文件吧
with open("中国.txt".encode(), 'w') as f:
pass
https://peps.python.org/pep-0529/
Windows控制台编码改为utf-8
sys.stdin, sys.stdout和sys.stderr默认编码都是utf-8,
当然,这是Windows的cmd里面出现乱码的原因,因为cmd默认编码是gbk
cmd修改编码很简单:chcp 65001
。想改回gbkchcp 936
新的dict实现
新dict的内存使用量会比之前减少20%到25%,而且现在的字典是有序的,当然这不是刻意保留的特性,未来可能会改变
新增secrets模块
就是一些随机数或者字符串的方法,一般用不上
https://docs.python.org/zh-cn/3.6/library/secrets.html#module-secrets
python3.7新增特性
新增dataclass
顾名思义就是一个装数据的类, 会自己生成__init__
、__repr__
、__eq__
和__hash__
@dataclass
class Point:
x: float
y: float
z: float = 0.0
p = Point(1.5, 2.5)
print(p) # produces "Point(x=1.5, y=2.5, z=0.0)"
新增importlib.resources
用于更好读取的import 导入的包,它不一定是文件系统内实际存在的文件或文件夹,比如在zip压缩包内等
import importlib.resources as res
import tkinter
text = res.read_text(tkinter, 'dialog.py', encoding='utf-8', errors='strict')
print(text)
python3.8
:=
if (n := len(a)) > 10:
print(f"List is too long ({n} elements, expected <= 10)")
上面的语法相当于n = len(a)
和n>10
,只是为了len这个方法不被调用两次。当然这个例子不是很直观。
while (block := f.read(256)) != '':
process(block)
当读取到空字符串的时候就停止,如果这个改成常规写法应该是下面这样的(或者直接while True),是不是变的更简洁了
block = f.read(256)
while block != '':
process(block)
block = f.read(256)
还有一种情况是在列表推导式中[f(x) for x in range(10) if f(x)>0]
f(x)被运行了两次[y for x in range(10) if (y:=f(x)) >0]
这样就只运行了一次
函数参数新增/
语法
和*
类似,看例子
def f(a, b, /, c, d, *, e, f):
print(a, b, c, d, e, f)
a, b参数不能使用关键词传参,只能传值。c,d既可以传值,也可以传键值,e,f只能传键值
比如:f(10, 20, 30, d=40, e=50, f=60)
是允许的,而f(10, b=20, c=30, d=40, e=50, f=60)
是错误的
f字符串新增=语法
user = 'eric_idle'
member_since = date(1975, 7, 31)
f'{user=} {member_since=}'
# "user='eric_idle' member_since=datetime.date(1975, 7, 31)"
具有外部数据缓冲区的 pickle 协议 5
pickle新增缓冲区来减少数据拷贝,与之前的Python版本的pickle可能存在不兼容的情况
新增importlib.metadata模块
用于读取模块的一些信息
>>> from importlib.metadata import version, requires, files
>>> version('requests')
'2.22.0'
>>> list(requires('requests'))
['chardet (<3.1.0,>=3.0.2)']
>>> list(files('requests'))[:5]
[PackagePath('requests-2.22.0.dist-info/INSTALLER'),
PackagePath('requests-2.22.0.dist-info/LICENSE'),
PackagePath('requests-2.22.0.dist-info/METADATA'),
PackagePath('requests-2.22.0.dist-info/RECORD'),
PackagePath('requests-2.22.0.dist-info/WHEEL')]
python3.9
字典之间新增|
和|=
运算符
首先给了个字典合并的几种方法
d = {'spam': 1, 'eggs': 2, 'cheese': 3}
e = {'cheese': 'cheddar', 'aardvark': 'Ethel'}
# 方法1
print({**d, **e})
# 方法2
from collections import ChainMap
print(dict(ChainMap(e, d)))
# 方法3
print(dict(d, **e))
#方法4
d.update(e)
print(d)
然后给出了python3.9的第五种方法: print(d | e)
注意d|e
和e|d
结果(顺序和值)可能是不一样的,这和之前的四种方法一样执行有先后的顺序
虽然|
很方便,但还是无法处理所有的情况,比如print({'a': [1, 2]} | {'a': [3, 4]})
是应该得到{'a': [1, 2, 3, 4]}
还是 {'a': [[1, 2], [3, 4]]}
,这种就只能自己写方法去实现了
字符串新增两个方法
实现如下
def removeprefix(self: str, prefix: str, /) -> str:
if self.startswith(prefix):
return self[len(prefix):]
else:
return self[:]
def removesuffix(self: str, suffix: str, /) -> str:
# suffix='' should not call self[:-0].
if suffix and self.endswith(suffix):
return self[:-len(suffix)]
else:
return self[:]
使用例子:
if test_func_name.startswith("test_"):
print(test_func_name[5:])
else:
print(test_func_name)
改为: print(test_func_name.removeprefix("test_"))