如何让eval()同时访问类实例变量与itertools模块函数?
优雅实现eval()仅访问实例变量与指定模块函数
要让eval()只能访问类实例instance的变量,同时允许访问itertools模块的函数,有两种更规范的实现方式,避免手动拼凑字典:
方式一:自动合并模块公开属性与实例命名空间
直接将itertools的公开属性(排除以下划线开头的私有属性)合并到实例的命名空间中,无需逐个指定函数:
import itertools # 筛选itertools的公开函数/属性 itertools_public = {k: v for k, v in vars(itertools).items() if not k.startswith('_')} # 合并实例命名空间与模块公开属性 eval_namespace = {**vars(instance), **itertools_public} # 执行eval result = eval(expr, eval_namespace)
这种方式会自动包含itertools的所有公开功能,适合需要完整使用模块的场景。
方式二:自定义命名空间类(高扩展性)
如果需要后续灵活添加其他模块或属性,可以定义一个命名空间类,统一管理可访问的资源:
import itertools class EvalNamespace: def __init__(self, instance): # 绑定实例的所有属性 self.__dict__.update(vars(instance)) # 绑定itertools的公开属性 self.__dict__.update({k: v for k, v in vars(itertools).items() if not k.startswith('_')}) # 创建命名空间实例 namespace = EvalNamespace(instance) # 执行eval result = eval(expr, namespace.__dict__)
这种方式扩展性强,后续要添加其他模块或自定义函数,只需在__init__中继续更新__dict__即可。
注意事项
- 无论哪种实现,都要严格限制
eval()的输入表达式,绝对不能用eval()处理不可信的用户输入,防止代码注入风险。 - 如果仅需
itertools的部分特定函数,你原本手动指定函数的写法其实也很直观合理,并非不规范,这种场景下无需刻意追求自动化合并。
内容的提问来源于stack exchange,提问作者Sasha
相关产品推荐
相关产品推荐

