3 ms·
If the only thing you want is to use the {identifier} syntax, without having to repeat `identifier` more than once, the simplest alternative is probably: >
by berdario 12y ago
If the only thing you want is to use the {identifier} syntax, without having to repeat `identifier` more than once, the simplest alternative is probably:
>>> package = "foo"
>>> whatever = "bar"
>>> "Enjoy {package}".format(**locals())
'Enjoy foo'
(disclaimer: I wouldn't actually use locals() like this in real code)
Also, if this thing is truly mangling bytecode, it's not portable between different python versions
But i'm not quite sure about that: I only skimmed the codebase, and that works seems to be done by interpy_untokenize, which boils down to some string mangling
Also, having expressions (or worse, statements... like it would be in ruby since there's no difference there) evaluated when evaluating a string is quite bad (this is not Haskell, and thus we cannot have guarantees that side effects won't happen)
Nice hack, btw
- csl 12y agoAlso, if this thing is truly mangling bytecode, it's not portable between different python versions [...] seems to be done by interpy_untokenize, which boils down to some string mangling It uses the Python file encoding property ("# coding: foobar") to rewrite the source code, not the bytecode, and they refer to pyxl as an inspiration. For a good explanation, see https://github.com/dropbox/pyxl https://github.com/dropbox/pyxl
- rraval 12y agoNote that `locals()` actually does funky things around enclosing scopes. Consider the following Python2/3 code: def outer(): x = 1 def inner(): print(x) print("x = {x}".format(**locals())) inner() outer() This actually prints the right thing when run: 1 x = 1 However, if you remove the `print(x)` line, both Python 2 and 3 don't hoist the enclosing `x` into `locals()` (since it can't see a single usage of that variable), resulting in a `KeyError`: Traceback (most recent call last): File "blah.py", line 7, in <module> outer() File "blah.py", line 5, in outer inner() File "blah.py", line 4, in inner print("x = {x}".format(**locals())) KeyError: 'x' Python 3 has the `nonlocal` keyword that you can use to indicate that you're using a variable from an enclosing scope so that it's properly introduced into `locals()` but Python 2 doesn't have this facility.
- wylee 12y agoThat doesn't seem funky to me, given that `x` in your example is in fact not local to `inner`. It may seem surprising, but it's consistent with how Python handles locals in general.
- rraval 12y agoI called it funky because `x` is never local to `inner`, but gets an entry inside `locals()` if `inner` uses it implicitly or explicitly with `nonlocal`. Non-funky behaviour would be to have an `enclosing()` that walks up the outer functions and returns the union of their `locals()`. Alternatively, a `vars()` which expands to all variables in scope (respecting LEGB) would be best given the context of variable interpolation.
- maxerickson 12y agostr.format_map takes a mapping directly.
- berdario 12y agoThanks! I'd edit my post if I could