简体   繁体   中英

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.

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.

You can always replace the list comprehension with a regular loop. Less fancy, but gives the same functionality.

Although I have Python 3.8.0 and the code works as expected - without any errors. , as my comment says, it's still possible to do these without any eval() .

You want to dynamically get a class from a module. You can use getattr() for this.

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

Output:

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>]

I'm not exactly sure why those ,0.5 suffixes were there ( __init__ arguments, maybe?) , but the "gist of it" is written above.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM