如何获取operator.itemgetter创建时使用的键列表?
问题
我创建了一个operator.itemgetter()对象,示例代码如下:
import operator keyfunc = operator.itemgetter("key1", "key2")
将该对象传递出去后,后续希望获取它创建时使用的键列表,比如想要实现类似下面的效果(但keys()方法实际不存在):
# 期望返回 ("key1", "key2") keys = keyfunc.keys()
可以看到这个对象内部肯定存储了这些键用于__call__方法,而且打印时会显示:
>>> print(keyfunc) operator.itemgetter('key1', 'key2')
但我查看dir(keyfunc)的输出时,没有找到能返回这些键的成员,官方文档里也没有对应的访问方法。
请问我是否需要解析它的字符串表示?或者有没有其他更好的方式,比如在传递对象时同时存储并传递这些键?
目前我想到的解析方式如下,但感觉不太规范:
import ast keys = ast.literal_eval(repr(keyfunc).replace("operator.itemgetter", ""))
解答
优先推荐:传递对象时同时保存键列表
这是最稳妥、最符合Python规范的做法。因为operator.itemgetter的内部实现是不公开的,依赖解析字符串表示的方式属于未定义行为,未来Python版本如果修改了repr的输出格式,这种方法就会失效。实现方式很简单,可以把
itemgetter对象和键列表打包在一起传递,比如用元组或者自定义类:import operator keys = ("key1", "key2") keyfunc = operator.itemgetter(*keys) # 传递时一起传 pass_along = (keyfunc, keys) # 后续使用时直接取keys retrieved_keyfunc, retrieved_keys = pass_along解析字符串表示的备选方案
如果你确实无法修改传递逻辑,只能从已有的itemgetter对象中提取键,那么你当前用ast.literal_eval的方式比直接用eval要安全得多(避免了代码注入风险)。不过需要注意几个边界情况:- 如果
itemgetter只传入了单个键,repr的输出会是operator.itemgetter('key1'),替换后ast.literal_eval会返回单个值而不是元组,需要处理这种情况:import ast import operator keyfunc_single = operator.itemgetter("key1") repr_str = repr(keyfunc_single).replace("operator.itemgetter", "") keys = ast.literal_eval(repr_str) # 转为统一的元组格式 keys = (keys,) if not isinstance(keys, tuple) else keys - 若键本身包含特殊字符(比如括号),这种替换方式可能出错,但实际场景中这种情况极少。
- 如果
总结来说,优先选择同时传递键列表的方案,解析字符串只能作为万不得已的备选。
内容的提问来源于stack exchange,提问作者moooeeeep
相关产品推荐
相关产品推荐

