Python中仅赋值函数多返回值之一的最快及最Pythonic方式
Python取多返回值单个结果:风格与性能全解析
咱们直接切入正题,先解决最核心的两个问题:哪种写法最地道,以及怎么靠谱地测性能。
1. 最符合Python风格的写法
毫无疑问,a, _ = fn() 是Python圈公认的最优写法!下划线_是大家默认的“占位符变量”,一眼就能看出来:“哦,这个返回值我就是故意忽略的”,可读性拉满。
对比其他几种写法:
a = fn()[0]虽然能跑,但不够直观——得反应过来函数返回的是可索引的序列(其实Python多返回值本质是元组语法糖,但新手可能没这个概念);a, b = fn()然后扔着b不管,不仅会造成变量冗余,静态检查工具(比如pylint)还会给你标红,其他开发者看到也会疑惑“这个b为啥不用?是不是漏写了逻辑?”;x = fn(); a=x[0]完全是画蛇添足,多了个中间变量x,既啰嗦又没必要。
2. 性能差异的底层原理
从Python解释器的执行逻辑来看,这几种写法的性能差异微乎其微,几乎可以忽略:
- 不管哪种写法,第一步都是让
fn()执行,返回一个元组(Python的多返回值本质就是返回元组的语法糖); a, _ = fn()是元组解包赋值,a = fn()[0]是元组索引取值,这两个操作的执行成本在解释器里几乎一致;- 你说测试结果波动大,大概率是因为
fn()内部的逻辑不稳定(比如涉及随机数、缓存、IO操作),或者timeit的测试次数太少导致的误差——毕竟赋值/索引这种操作的耗时都是纳秒级的,一点点波动就会让结果看起来差异很大。
3. 怎么做好timeit测试?
要得到靠谱的计时结果,得注意这几点:
- 用完全稳定的测试函数:别让
fn()带副作用,比如就返回固定值:def fn(): return 1, 2 - 拉满测试次数:默认的测试次数可能不够,直接设成千万级,比如
number=10_000_000,用大次数抹平小误差; - 多次测试取平均:单次测试可能受系统负载影响,多跑几次取平均值更靠谱;
- 明确作用域:用
globals=globals()把函数和变量的作用域传给timeit,避免环境不一致导致的误差。
给你一个现成的测试代码:
import timeit def fn(): return 1, 2 # 跑四次测试 test1 = timeit.timeit("a = fn()[0]", globals=globals(), number=10_000_000) test2 = timeit.timeit("a, _ = fn()", globals=globals(), number=10_000_000) test3 = timeit.timeit("a, b = fn()", globals=globals(), number=10_000_000) test4 = timeit.timeit("x = fn(); a = x[0]", globals=globals(), number=10_000_000) # 打印结果 print(f"写法1:a = fn()[0] → {test1:.4f}秒") print(f"写法2:a, _ = fn() → {test2:.4f}秒") print(f"写法3:a, b = fn() → {test3:.4f}秒") print(f"写法4:x = fn(); a=x[0] → {test4:.4f}秒")
跑出来你会发现,写法1和2的时间几乎没差,写法3慢一丢丢(多赋值了一个变量),写法4是最慢的(多了一次变量绑定)。
总结
- 日常开发优先选
a, _ = fn(),既地道又好懂; - 性能上不用纠结,除非你要跑上千万次调用,否则这点差异完全感知不到;
- 测性能的时候一定要控制变量、拉满次数,才能得到靠谱的结果。
内容的提问来源于stack exchange,提问作者dkv
相关产品推荐
相关产品推荐

