当前位置:首页>python>探索 Python 函数的隐藏属性,用了就是高级工程师

探索 Python 函数的隐藏属性,用了就是高级工程师

  • 2026-10-11 07:45:38
探索 Python 函数的隐藏属性,用了就是高级工程师
写了十年 Python,我发现一个扎心的事实:大部分人学的是语法,高手玩的是内置特性。
同样是写函数,新手写 30 行,老手 5 行搞定。
不是因为聪明,是知道 Python 已经替你写好了。
今天这 5 个技巧,每一个都能让你的代码短一截、快一截、优雅一截。 

1. 用 __slots__ 减少实例内存

刚学 Python 的时候我这么写过:

class Point:    def __init__(self, x, y):        self.x = x        self.y = y# 每个实例都有 __dict__,大量实例时浪费内存

Python 内置了更专业的方案:

class Point:    __slots__ = ('x', 'y')    def __init__(self, x, y):        self.x = x        self.y = yp = Point(1, 2)print(p.x, p.y)# p.z = 3  # AttributeError! 不能添加额外属性

__slots__ 告诉 Python 只为列出的属性分配空间,省去 __dict__ 的开销。百万级实例时内存可减少 40-50%,访问速度也更快。


2. 用 type hints 标注函数签名

很多教程会教你这么写:

def calculate_area(width, height):    return width * height# 调用者不知道参数类型和返回类型

更专业的方案是使用 Python 内置属性:

def calculate_area(width: float, height: float) -> float:    """计算矩形面积"""    return width * height# 复杂类型from typing import Optionaldef find_user(name: str) -> Optional[dict]:    users = {'Alice': {'age': 30}}    return users.get(name)

类型注解让代码自文档化,IDE 可以据此提供自动补全和类型检查,配合 mypy 还能在运行前发现类型错误,是现代 Python 项目的标配。


3. 用生成器节省内存

看起来没问题,但其实有更好的方式:

def get_squares(n):    result = []    for i in range(n):        result.append(i ** 2)    return result  # 百万级数据占用大量内存for x in get_squares(1000000):    pass

老手一般这么写:

def get_squares(n):    for i in range(n):        yield i ** 2  # 惰性生成,内存恒定for x in get_squares(1000000):    pass  # 内存占用极小

yield 将函数变为生成器,按需产出值而非一次性构建完整列表。处理百万级数据时,内存从 O(n) 降到 O(1),是大数据处理的基本功。


4. 用 contextmanager 自定义上下文管理器

搜一下 Stack Overflow,排第一的答案通常长这样:

class Timer:    def __enter__(self):        self.start = time.perf_counter()        return self    def __exit__(self, *args):        self.elapsed = time.perf_counter() - self.start        print(f'Elapsed: {self.elapsed:.4f}s')

一行代码就能搞定:

import timefrom contextlib import contextmanager@contextmanagerdef timer(label='Block'):    start = time.perf_counter()    try:        yield    finally:        elapsed = time.perf_counter() - start        print(f'{label}: {elapsed:.4f}s')with timer('Data processing'):    time.sleep(0.1)

contextmanager 装饰器让你用生成器函数创建上下文管理器,比写 __enter__/__exit__ 类简洁得多。yield 前是进入逻辑,yield 后是退出逻辑。


5. 用 singledispatch 实现函数重载

看起来没问题,但其实有更好的方式:

def process(data):    if isinstance(data, str):        return data.upper()    elif isinstance(data, list):        return [x * 2 for x in data]    elif isinstance(data, int):        return data ** 2

用对了工具,代码量直接砍半:

from functools import singledispatch@singledispatchdef process(data):    raise TypeError(f'Unsupported type: {type(data)}')@process.register(str)def _(data):    return data.upper()@process.register(list)def _(data):    return [x * 2 for x in data]print(process('hello'))    # 'HELLO'print(process([1, 2, 3]))  # [2, 4, 6]

singledispatch 实现基于第一个参数类型的函数重载,比一连串 isinstance 更优雅可扩展。新类型只需注册新实现,不修改原函数。


速查表

场景别这样写试试这样
减少实例内存普通 class 带 __dict____slots__ 限定属性
函数签名不清晰参数无类型标注type hints 标注类型
大数据占内存result.append() 构建列表yield 生成器按需产出
自定义上下文管理器写 __enter__/__exit__ 类@contextmanager 一行搞定
多类型函数重载一连串 isinstance@singledispatch 注册分发

以上就是函数技巧的 5 个实用技巧,每个都是我在实际项目中踩过坑才总结出来的。先收藏起来,勤加练习,一步步进阶为高级工程师。

评论区聊聊:这 5 个技巧里哪个你之前不知道?

下期预告:内置模块专场


关于作者

写了 10 年 Python,赶上了机器学习的热潮,又撞上了大模型的浪头,每次以为学明白了,行业又变了一次。

把自己踩过的坑、走过的弯路、看过的热闹,说给还在路上的人听。

关注「鲁叶的Python」,和我一起穿越迷茫期。

最新文章

随机文章