Python中的奇技淫巧

1. 海象运算符 :=(Python 3.8+)

用途说明:在表达式中直接赋值并返回值,减少冗余语句。例如在 if 语句中计算长度并使用,无需先单独计算赋值。
示例

if (n := len(data)) > 10:
    print(f"数据量为 {n}")

上例中 (n := len(data)) 在判断时给 n 赋值,同时作为整个表达式的值。

2. 格式化字符串(f-strings)(Python 3.6+)

用途说明:在字符串前加 fF 后引号,在大括号中嵌入 Python 表达式,简洁地进行格式化。支持任意表达式、格式说明符等。
示例

name = "Alice"
age = 30
print(f"{name} 的年龄是 {age} 岁")  # Alice 的年龄是 30 岁

f-string 是 Python 3.6 引入的语言特性,相比 % 格式化和 str.format() 更直观且性能更优。

3. f-string 调试表达式(Python 3.8+)

用途说明:在 f-string 表达式末尾添加 =,可以打印表达式本身和结果,便于调试。
示例

value = 42
print(f"{value=}")  # 输出 "value=42"

这种语法自 3.8 版起可用,能快速显示变量名和其值。

4. 数字字面量中的下划线(Python 3.6+)

用途说明:在整数或浮点数字面量中使用下划线 _ 作为分隔符,增强可读性,不影响值。
示例

million = 1_000_000
hex_val = 0xCAFE_F00D
binary = 0b_1010_1011

以上代码合法,自 Python 3.6 起支持在数字中任意位置加 _ ,可显著提高长数字的可读性。

5. 字典合并运算符 ||=(Python 3.9+)

用途说明:可以使用 | 将两个字典合并生成新字典,用 |= 更新原字典而非返回。
示例

a = {'x':1, 'y':2}
b = {'y':3, 'z':4}
c = a | b       # {'x':1, 'y':3, 'z':4}
a |= b          # a 现在也变成 {'x':1, 'y':3, 'z':4}

这在 Python 3.9 以后成为内置语法,无需 copy()update(),写法简洁明了。

6. 内置容器类型可作泛型(Python 3.9+)

用途说明typing 模块逐步支持直接使用内置类型来表示泛型。Python 3.9 以后,列表、字典、集合等类型都可以直接用中括号标注类型。
示例

names: list[str] = ["Alice", "Bob"]     # 等价于 typing.List[str]
point: dict[str, float] = {"x":0.0, "y":1.0}

PEP 585 使得 list[int] 等写法生效,不再需要导入 typing.List,使代码更简洁。

 

7. 新增字符串去除前后缀方法(Python 3.9+)

用途说明:提供 str.removeprefix(prefix)str.removesuffix(suffix) 方法,直接去除字符串的固定前缀或后缀,返回去除后的新字符串,如果不存在则返回原字符串。
示例

s = "unittest"
print(s.removeprefix("unit"))   # 输出 "test"
print(s.removesuffix("test"))   # 输出 "unit"

这两个方法从 Python 3.9 开始可用,避免了手动检查索引或使用正则等繁琐步骤。

 

8. 类型提示中的联合类型 X | Y(Python 3.10+)

用途说明:使用 | 运算符简写联合类型,比如 int | None 相当于 Optional[int],无需使用 typing.Union
示例

def greeting(name: str | None) -> str:
    return f"Hello {name}" if name else "Hello world"

Python 3.10 引入此语法,使类型提示更自然简洁。

9. 用户定义类型守卫(TypeGuard)(Python 3.10+)

用途说明typing.TypeGuard 用于自定义类型检查函数,让类型检查器理解某个函数验证参数类型后,后续代码对类型更精确。
示例

from typing import TypeGuard

def is_str_list(val: list[object]) -> TypeGuard[list[str]]:
    return all(isinstance(x, str) for x in val)

values: list[object] = ["a", "b", 3]
if is_str_list(values):
    # 此处 values 被推断为 list[str]
    print(values[0].upper())

Python 3.10 引入 PEP 647 提供 TypeGuard,上述例子中 is_str_list 让类型检查器知道在 if 分支中 values 中元素全为 str

10. yield from 生成器委托(Python 3.3+)

用途说明yield from 可以把一个子生成器的所有产出直接转发到外层生成器,用于简化嵌套迭代、代理生成器等。
示例

def subgen():
    for i in range(3):
        yield i

def gen():
    yield from subgen()
    yield 3

print(list(gen()))  # [0, 1, 2, 3]

自 Python 3.3 起支持,大大简化了从一个生成器顺序产出值的代码编写。

11. 原生协程语法 async def / await(Python 3.5+)

用途说明:使用 async def 定义异步协程函数,使用 await 等待异步操作。使异步编程写法与同步类似,可读性高。
示例

import asyncio

async def hello():
    await asyncio.sleep(1)
    print("Hello")

async def main():
    await asyncio.gather(hello(), hello())

asyncio.run(main())

Python 3.5 引入 PEP 492 后,原生支持 async/await 关键字,无需第三方库即可编写协程代码。

12. 异步推导式(Python 3.6+)

用途说明:可以在异步环境中使用 [...]{...}(...) 推导式配合 async forasync if 来创建异步生成器、列表或集合。
示例

async def async_iter():
    for i in range(3):
        yield i
result = [i * 2 async for i in async_iter() if i % 2 == 1]
print(result)  # [2, 6]

PEP 530 在 Python 3.6 中加入此功能,使得异步数据处理更为简洁,不必显式循环累加。

13. 异步生成器(Python 3.6+)

用途说明:在 async def 函数中使用 yield,创建异步生成器,可在异步函数之间逐步产出值并用 async for 迭代。
示例

async def agen(n):
    for i in range(n):
        yield i
async def consume():
    async for v in agen(3):
        print(v)
asyncio.run(consume())  # 输出 0,1,2

14. contextlib.suppress(Python 3.4+)

用途说明contextlib.suppress(*exceptions) 创建一个上下文管理器,自动忽略指定的异常,使代码更简洁。
示例

from contextlib import suppress
with suppress(FileNotFoundError):
    os.remove("not_exists.txt")  # 文件不存在也不会抛出异常

15. contextlib.redirect_stdout/redirect_stderr(Python 3.4+)

用途说明:重定向标准输出或错误流到指定文件或对象,非常方便进行输出捕获。
示例

from contextlib import redirect_stdout
import io
buf = io.StringIO()
with redirect_stdout(buf):
    print("This is captured")
print("Captured:", buf.getvalue())

16. contextlib.nullcontext(Python 3.7+)

用途说明:提供一个什么都不做的上下文管理器,可作为条件性 with 的占位符。当不需要实际的资源管理时使用,保持代码结构一致。
示例

from contextlib import nullcontext
use_context = False
cm = open("file.txt") if use_context else nullcontext("dummy")
with cm as f:
    print(f)  # 如果 use_context False,f 就是字符串 "dummy"

阅读剩余
THE END