Py学习  »  Python

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

机器学习初学者 • 7 月前 • 305 次点击  

今天跟大家介绍的这几个功能,并不是像你平时看到的那种“隐藏在显而易见的地方”的功能,而是需要对Python源代码有一定的专研,而后才能发现这些特性。

今天选择了5 个 Python 特性,这些特性在大部分教程中很少提及,但却能解决非常实际的问题— — 并且做得干净利落没有任何多余的内容样板代码也很少

接下来就跟云朵君一起看看吧~

1.contextlib.suppress:悄悄地kill异常

问题:你想要忽略一个非常具体的异常,但try/except仅为了这一点而编写块却感觉有点大材小用。

你可以这样写:

try:
    os.remove('tempfile.txt')
except FileNotFoundError:
    pass

或者你可以这样写——优雅的、Pythonic 的、 Jedi 的方式:

from contextlib import suppress

with 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 sys
sys.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 Literal

def connect(mode: Literal['read''write']):
    ...

现在,如果你传递除'read''write'之外的任何内容,你的 IDE 或静态类型检查器(如mypy甚至会在你运行代码之前尖叫

def 


    
get_user(role: Literal['admin''moderator''user']):
    ...

这使得你的 API 具有自文档性安全性健壮性— — 无需编写if块或自定义验证器。

这是动态语言中简洁的编译时验证。而且,它与pydanticFastAPI和现代工具完美兼容。

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, abstractmethod

class 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或框架时非常有用——灵活性胜过僵化的层次结构。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/185286