Python自定义函数多输出场景用字典替代元组的合理性及简化方案
问题1:返回字典的做法是否存在不妥?
完全不存在本质上的不妥,这是非常适合快速迭代、多返回值场景的合理实现,你提到的两个核心优势完全成立:
- 不需要对齐返回顺序,增删返回值不需要修改所有调用处的拆包代码,非常适配NLP研究场景频繁调整输出的需求
- 键名是命名空间隔离的,不会和全局变量产生命名冲突
其他开发者使用较少的核心原因是多数业务场景返回值只有2-3个,元组拆包足够简单;同时传统字典没有静态类型提示,键名拼写错误只能运行时发现,IDE补全支持较差。如果想要补全这些短板同时保留你的两个核心需求,还有几个成熟的替代方案可以选择:
typing.NamedTuple:定义一次字段,返回实例可以用属性访问(output.sum),也可以像元组一样拆包,不可变特性可以避免误修改返回值@dataclasses.dataclass:比NamedTuple更灵活,支持可变属性、默认值、自定义方法,Python 3.7+标准库自带pydantic.BaseModel:额外支持类型校验、自动序列化,适合需要严格校验返回值合法性的场景
dataclass示例:
from dataclasses import dataclass @dataclass class FunOutput: a: int b: int c: int sum_: int prod_: int def my_fun_dataclass(a,b,c): sum_ = a+b+c prod_ = a*b*c return FunOutput(a=a, b=b, c=c, sum_=sum_, prod_=prod_) output = my_fun_dataclass(1,2,3) print(output.sum_) # IDE自动补全,静态类型检查可以提前捕获拼写错误
问题2:如何避免重复书写变量名?
方案1:直接使用locals()(适合极快速迭代的临时脚本)
如果函数末尾除了要返回的变量没有其他额外局部变量,可以直接返回locals(),一行代码完成返回:
def my_fun_dict(a,b,c): sum_ = a+b+c prod_ = a*b*c return locals() output = my_fun_dict(1,2,3) print(output['sum_'])
注意:这个方法会把函数内所有局部变量都返回,如果中间定义了临时变量会被带出去,仅适合逻辑简单的小函数快速开发场景。
方案2:实现你提到的output_dict工具函数
通过inspect模块获取调用侧的变量名,完全符合你设想的用法:
import inspect def output_dict(*args): frame = inspect.currentframe().f_back locals_map = frame.f_locals return {name: locals_map[name] for name in args} # 用法和你预想的完全一致 def my_fun_dict(a,b,c): sum_ = a+b+c prod_ = a*b*c return output_dict('a', 'b', 'c', 'sum_', 'prod_')
方案3:dataclass+**locals()(符合Pythonic规范的推荐方案)
如果使用dataclass的话可以用**locals()自动传参,不需要重复写变量名,同时保留类型提示、IDE补全的优势,是工业界和科研界都广泛使用的写法:
from dataclasses import dataclass @dataclass class FunOutput: a: int b: int c: int sum_: int prod_: int def my_fun_dataclass(a,b,c): sum_ = a+b+c prod_ = a*b*c return FunOutput(**locals())
内容的提问来源于stack exchange,提问作者BioBroo
相关产品推荐
相关产品推荐

