Short form for string.format (..., ** locals ())

I usually use the following pattern (as mentioned in this question ):

a=1 s= "{a}".format(**locals()) 

I think this is a great way to write easy to read code.

It is sometimes useful to “chain” string formats to “modulate” the creation of complex strings:

 a="1" b="2" c="{a}+{b}".format(**locals()) d="{c} is a sum".format(**locals()) #d=="1+2 is a sum" 

Pretty soon, code is scanned using X.format(**locals()) . To solve this problem, I tried to create a lambda:

 f= lambda x: x.format(**locals()) a="1" b="2" c= f("{a}+{b}") d= f("{c} is a sum") 

but this raises a KeyError as locals() are lambda locales.

I also tried applying the format only to the last line:

 a="1" b="2" c="{a}+{b}" d="{c} is a sum".format(**locals()) #d=="{a}+{b} is a sum" 

But this does not work, since python only formats once. Now I can write a function that formats several times while you have nothing more to do:

 def my_format( string, vars ): f= string.format(**vars) return f if f==string else my_format(f, vars) 

but I wonder: is there a better way to do this?

+8
scope python string lambda string-formatting
Oct 23 '13 at 18:50
source share
4 answers

f = lambda x, l=locals(): x.format(**l) seems to work ...

and if you need a version that is a bit more comprehensive (and probably a lot slower):

 fg = lambda x, l=locals(), g=globals(): x.format(**dict(g.items() + l.items())) 

will find characters in locales or global characters.

+4
Oct 23 '13 at 18:55
source share

If you need to do this only in the function area as a local shortcut, the following will work:

 def formatter(fmt, loc=locals()): return fmt.format(**loc) 

However, this will associate the value returned by locals() during the declaration of the function, and not with the execution, so it will not be updated as the values ​​change and will not be useful when called from any other area.

If you want to access the calling locals method, you need an inspect call stack ( http://docs.python.org/2/library/inspect.html )

 import inspect def formatter(fmt): parent = inspect.stack()[1][0] # 1 = the previous frame context # 0 = the frame object return fmt.format(**parent.f_locals) 

Note that this may not work for python implementations that are not CPython.

Now you can do:

 a = "1" b = "2" c = formatter("{a}+{b}") d = formatter("{c} is a sum") 
+2
Oct 23 '13 at
source share

This is not single line, but it works:

 def fmt(s, l=locals()): while '{' in s: s = s.format(**l) return s a="1" b="2" c="{a}+{b}" d="{c} is a sum" print fmt(d) # 1+2 is a sum 

Here's a single line (and slightly less efficient) recursive version:

 fmt = lambda s, l=locals(): fmt(s.format(**l), l=l) if '{' in s else s 
0
Oct 23 '13 at 19:27
source share

Starting with Python 3.6, the effect **locals() already included in string#format or rather, in formatted string literals.

See also PEP 498 and Python 3.6 Release Notes .

0
Apr 10 '17 at 9:26
source share



All Articles