I have some code that does an awful lot of string formatting, Often, I end up with code along the lines of:
"...".format(x=x, y=y, z=z, foo=foo, ...)
Where I'm trying to interpolate a large number of variables into a large string.
Is there a good reason not to write a function like this that uses the inspect
module to find variables to interpolate?
import inspect
def interpolate(s):
return s.format(**inspect.currentframe().f_back.f_locals)
def generateTheString(x):
y = foo(x)
z = x + y
# more calculations go here
return interpolate("{x}, {y}, {z}")
String formatting uses a process of string interpolation (variable substitution) to evaluate a string literal containing one or more placeholders, yielding a result in which the placeholders are replaced with their corresponding values.
Strings are one of the most used and essential data types in Python. With that said, proper text formatting makes code and data much easier to read and understand.
In java, String format() method returns a formatted string using the given locale, specified format string, and arguments. We can concatenate the strings using this method and at the same time, we can format the output concatenated string. Parameter: The locale value to be applied on the format() method.
Update: Python 3.6 has this feature (a more powerful variant) builtin:
x, y, z = range(3)
print(f"{x} {y + z}")
# -> 0 3
See PEP 0498 -- Literal String Interpolation
It[manual solution] leads to somewhat surprising behaviour with nested functions:
from callerscope import format
def outer():
def inner():
nonlocal a
try:
print(format("{a} {b}"))
except KeyError as e:
assert e.args[0] == 'b'
else:
assert 0
def inner_read_b():
nonlocal a
print(b) # read `b` from outer()
try:
print(format("{a} {b}"))
except KeyError as e:
assert 0
a, b = "ab"
inner()
inner_read_b()
Note: the same call succeeds or fails depending on whether a variable is mentioned somewhere above or below it.
Where callerscope
is:
import inspect
from collections import ChainMap
from string import Formatter
def format(format_string, *args, _format=Formatter().vformat, **kwargs):
caller_locals = inspect.currentframe().f_back.f_locals
return _format(format_string, args, ChainMap(kwargs, caller_locals))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With