除非像eval 这样的安全漏洞,否则不能在mapper.py 中使用名称a,除非该名称在mapper.py 中的某处定义或从另一个模块导入。没有办法让mapper.py 自动且静默地访问来自不同模块的值a。
此外,如果您只是在示例中的字典中使用它,则 a.foo 将在创建字典后立即进行评估。它不会等到您真正调用该函数;一旦它评估a.foo 来创建字典,它就会失败,因为它不知道a 是什么。
您可以通过将元素包装在函数中来解决第二个问题(为简洁起见,使用 lambda):
Mapper = {'test': lambda: a.foo}
。 . .但这仍然无济于事,除非你能以某种方式让a 在mapper.py 中可用。
一种可能性是通过“神秘”对象参数化您的Mapper,然后将该对象从外部传入:
# mapper.py
Mapper = {'test': lambda a: a.foo}
# other module
from mapper import Mapper
Mapper['test'](a)()
或者,类似于mgilson 的建议,您可以通过Mapper 以某种方式“注册”对象a。这让您只需传递对象a 一次即可注册它,然后您不必每次调用都传递它:
# mapper.py
Mapper = {'test': lambda a: Mapper['a'].foo}
# other module
from mapper import Mapper
Mapper['a'] = a
Mapper['test']()()
请注意末尾的两组括号:一组用于评估 lambda 并提取您要调用的函数,第二组用于实际调用该函数。你可以做一个类似的处理,而不是使用Mapper['a']作为参考,使用模块级变量:
# mapper.py
Mapper = {'test': lambda: a.foo}
# other module
import mapper
Mapper = mapper.Mapper
mapper.a = a
Mapper['test']()()
请注意,这需要您执行import mapper 才能在其他模块中设置模块变量。
您可以通过为Mapper 使用自定义类而不是常规字典来简化这一点,并让该类在其__getitem__ 中执行一些工作以查看“已知位置”(例如,读取一些模块变量) 用作评估a 的基础。不过,这将是一个更重的解决方案。
最重要的是,您根本不能(同样,不使用eval 或其他此类漏洞)在mapper.py 中编写使用未定义变量a 的代码,然后在其中定义变量a另一个模块并让mapper.py 自动知道这一点。某处必须有一些代码行“告诉”mapper.py 您希望它使用 a 的什么值。