Python 3:使用列表理解将字符串转换为变量

Python 3: strings to variable with list comprehension

在Python 2.7中我曾经可以使用下面的代码(我使用的是emcee包):

def main():
    from emcee import moves
    emcee_moves = ['KDEMove(),0.5', 'DEMove(),0.5']
    mv = [(eval("moves." + _)) for _ in emcee_moves]

if __name__ == '__main__':
    main()

我使用它是因为我通过一个输入参数文件(这是一个更大的代码的一小部分)提供 "moves",这意味着它们被读取为字符串。在 Python 3.x 这现在抛出:

*** NameError: name 'moves' is not defined

这显然与 this wont fix bug as mentioned in this old question: 有关。

我还了解到,通常不鼓励使用 eval()。那么我的问题是:如何复制上面用于 Python 2.7 的代码?


编辑

这是失败的实际代码。需要一个函数里面,否则不会失败。

正如皮特所说,您的示例适用于 python 3.6.8。 然而,另一种做你想做的事情的方法是:

from emcee import moves
emcee_moves = [('KDEMove', 0.5), ('DEMove', 0.5)]
mv = [(getattr(moves, method)(), val) for method, val in emcee_moves]

getattr 通常比 eval 更安全。

您始终可以用常规循环替换列表理解。不太花哨,但功能相同。

尽管 I have Python 3.8.0 and the code works as expected - without any errors.,正如我的评论所说,仍然可以在没有任何 eval().

的情况下完成这些操作

您想从模块中动态获取 class。您可以为此使用 getattr()

from emcee import moves
emcee_moves = ['KDEMove', 'DEMove']
mv = [getattr(moves, _)() for _ in emcee_moves]

输出:

In [22]: mv = [getattr(moves, _)() for _ in emcee_moves]

In [23]: mv
Out[23]:
[<emcee.moves.kde.KDEMove at 0x7f2bf8b98a90>,
 <emcee.moves.de.DEMove at 0x7f2bf90b08e0>]

我不太确定为什么会有那些 ,0.5 后缀 __init__ 参数,也许?),但是 "gist of it"上面写着