这 5 个 Python 功能绝了,你很少见~

本文约2000字,建议阅读5分钟
本文介绍了5个在多数 Python 教程中较少提及、但能高效解决实际问题的实用特性。
本文约2000字,建议阅读5分钟
本文介绍了5个在多数 Python 教程中较少提及、但能高效解决实际问题的实用特性。今天跟大家介绍的这几个功能,并不是像你平时看到的那种“隐藏在显而易见的地方”的功能,而是需要对Python源代码有一定的专研,而后才能发现这些特性。
今天我们选择了5 个 Python 特性,这些特性在大部分教程中很少提及,但却能解决非常实际的问题— — 并且做得干净利落,没有任何多余的内容,样板代码也很少。
接下来就跟我们一起看看吧~
1.contextlib.suppress:悄悄地kill异常
问题:你想要忽略一个非常具体的异常,但try/except仅为了这一点而编写块却感觉有点大材小用。
你可以这样写:
try: os.remove('tempfile.txt')except FileNotFoundError: pass
或者你可以这样写——优雅的、Pythonic 的、 Jedi 的方式:
from contextlib import suppresswith suppress(FileNotFoundError): os.remove('tempfile.txt')
就是这样。
没有try,没有except,没有pass。只是清晰易读的意图:
“我想运行这个程序。如果发生这个特定的错误,请悄悄地继续运行。”
何时使用:
-
删除文件或关闭套接字
-
清理临时文件
-
关闭可能不存在的服务
你甚至可以抑制多个异常。
with suppress(FileNotFoundError, PermissionError): os.remove('config.yaml')
这种功能可以让你的代码变得 10 倍简洁 — — 而且它隐藏在contextlib大多数人只会接触的模块深处@contextmanager。
2.sys.setrecursionlimit: 在递归攻击你之前先破解它
你正在编写一个递归算法 — — 比如树遍历或 DFS — — 然后 Python 突然放弃了:
RecursionError: maximum recursion depth exceeded
这是因为 CPython 的默认递归限制保守为1000。
大多数教程不会告诉你的是:你可以提高这个限制——只需一行代码即可。
import syssys.setrecursionlimit(10**6)
完全有效的递归代码中不再出现奇怪的堆栈溢出。
何时使用:
-
自定义解析器
-
递归数据结构遍历
-
回溯算法
专业提示:除非你了解程序的调用堆栈深度,否则请勿随意将其设置过高。每次调用都会占用内存。但如果你知道自己在做什么,这将带来显著的改变。
因为大多数人都害怕触碰sys设置,所以你经常回忽略他。
3. typing.Literal:安全字符串的秘诀
你有一些函数可以接受字符串,但实际上它们只接受几个有效值。像这样:
def connect(mode: str): if mode not in ['read', 'write']: raise ValueError("Invalid mode")
这没问题,但这是运行时验证。为什么不把它转移到类型检查器呢?
进入Literal:
from typing import Literaldef connect(mode: Literal['read', 'write']): ...
现在,如果你传递除'read'或'write'之外的任何内容,你的 IDE 或静态类型检查器(如mypy)甚至会在你运行代码之前尖叫。
def get_user(role: Literal['admin', 'moderator', 'user']): ...
这使得你的 API 具有自文档性、安全性和健壮性— — 无需编写if块或自定义验证器。
这是动态语言中简洁的编译时验证。而且,它与pydantic、FastAPI和现代工具完美兼容。
Bonus Flex:也适用于Union:
def get_data(format: Literal['json', 'xml'] | None = None): ...
4.__missing__:dict子类中被低估的魔法方法
你正在使用字典并想要自定义如何处理丢失的键 - 但defaultdict没有给你足够的控制权。
是时候覆盖支持这一切的隐藏方法了:__missing__。
class AutoDict(dict): def __missing__(self, key): value = self[key] = f"[{key} not found]" return value
用法:
d = AutoDict()print(d['python']) # [未找到python] print(d['java']) # [未找到java]
这里发生了什么?
当找不到某个键时,__missing__就会触发。你可以记录、转换、回退,甚至自动插入值。
高级用例:
跟踪未知的访问模式:
class AccessTracker(dict): def __missing__(self, key): print(f"Key {key} accessed but not found.") raise KeyError(key)
重要性:
它让你能够对字典行为进行精准的控制。大多数开发者甚至不知道__missing__的存在——除了官方的 Python 数据模型参考之外,它通常没有相关的文档。
5. __subclasshook__:让你的 API 更加安全
你已经定义了一个抽象基类,但你不想强迫人们从它继承 -- 你只是希望他们实现正确的方法。
Python 将此称为结构类型— — 这就是你会喜欢__subclasshook__的原因。
from abc import ABC, abstractmethodclass JsonSerializable(ABC): @abstractmethod def to_json(self): pass @classmethod def __subclasshook__(cls, C): if any("to_json" in B.__dict__ for B in C.__mro__): return True return NotImplemented
现在,如果一个类有一个to_json()方法——无论是否继承——它都会被视为子类。
class MyClass: def to_json(self): return '{"hello": "world"}'print(issubclass(MyClass, JsonSerializable)) # True
无需强制继承,即可获得类似接口的行为。这在构建插件、API或框架时非常有用——灵活性胜过僵化的层次结构。
编辑:于腾凯
校对:林亦霖
关于我们
数据派THU作为数据科学类公众号,背靠清华大学大数据研究中心,分享前沿数据科学与大数据技术创新研究动态、持续传播数据科学知识,努力建设数据人才聚集平台、打造中国大数据最强集团军。

新浪微博:@数据派THU
微信视频号:数据派THU
今日头条:数据派THU
更多推荐

所有评论(0)