Search code examples
pythonevalpython-3.7

Python 3: strings to variable with list comprehension


In Python 2.7 I used to be able to use the following code (I'm using the emcee package):

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()

I use this because I feed the "moves" through an input parameters file (this is a little portion of a much larger code), which means they are read as strings. In Python 3.x this now throws:

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

This is apparently related to this wont fix bug as mentioned in this old question: Eval scope in Python 2 vs. 3.

I've also read that using eval() is generally discouraged. My question is then: how do I replicate the above code which used to work in Python 2.7?


Edit

This is the actual code that fails. It need to be inside a function, otherwise it won't fail.


Solution

  • As Pete said, your example works for python 3.6.8. However, another way of doing what you want is:

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

    getattr is generally safer than eval.