----- Original Message ----- > From: Steven D'Aprano <st...@pearwood.info> > To: tutor@python.org > Cc: > Sent: Tuesday, November 4, 2014 4:08 AM > Subject: Re: [Tutor] eval use (directly by interpreter vs with in a script) > > On Mon, Nov 03, 2014 at 09:33:18AM -0800, Albert-Jan Roskam wrote: > > >> >Real question is what you're trying to do. eval() and exec() are > to be >> >avoided if possible, so the solutions are not necessarily the easiest. >> >> I sometimes do something like >> ifelse = "'teddybear' if bmi > 30 else > 'skinny'" >> weightcats = [eval(ifelse) for bmi in bmis] >> >> Would this also be a *bad* use of eval? It can be avoided, but this is so > concise. > > Two lines, 92 characters. This is more concise: > > weightcats = ['teddybear' if bmi > 30 else 'skinny' for bmi > in bmis]
Aaah *slap against forehead*! I did not know this is legal. MUCH nicer indeed > One line, 68 characters. And it will be faster too. On average, you > should expect that: > > eval(expression) > > is about ten times slower than expression would be on its own. > > In my opinion, a *minimum* requirement for eval() is that you don't know > what the code being evaluated will be when you're writing it. If you can > write a fixed string inside the eval, like your example above, or a > simpler case here: > > results = [eval("x + 2") for x in values] > > then eval is unneccessary and should be avoided, just write the > expression itself: > > results = [x + 2 for x in values] > > > You *may* have a good reason for using eval if you don't know what the > expression will be until runtime: > > results = [eval("x %c 2" % random.choice("+-/*")) for x in > values] > > > but even then there is often a better way to get the same result, e.g. > using getattr(myvariable, name) instead of eval("myvariable.%s" % > name). > In the case of the random operator, I'd write something like this: > > OPERATORS = {'+': operator.add, '-': operator.sub, > '/': operator.truediv, '*': operator.mul} > results = [OPERATORS[random.choice("+-/*")](x, 2) for x in values] > > which in this case is a little longer but safer and probably faster. > It's also more easily extensible to a wider range of operators and even > functions. Hmm, I get 1900 occurrences of eval() (and 700 of frozenset, just curious) in Python. That's MUCH, I must be something wrong, but I am rushing now! import os import sys import collections os.chdir(os.path.dirname(sys.executable)) cmds = ["eval(", "frozenset"] counter = collections.Counter() for root, dirs, files in os.walk(".", topdown=False): for name in files: if name.endswith(".py"): contents = open(os.path.join(root, name)) for line in contents: if not line.startswith("#"): for cmd in cmds: if cmd in line: counter[cmd] += 1 print counter _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor