14

I'd like to use Python f-string for its syntactical simplicity, compared to string.Template() or other approach. However, in my application, the string is loaded from file, and the values of the variable can only be provided later.

If there a way to invoke fstring functionality separate from the string definition? Hopefully code below will better explain what I hope to achieve.

a = 5
s1 = f'a is {a}' # prints 'a is 5'

a = 5
s2 = 'a is {a}'
func(s2) # what should be func equivalent to fstring
0

6 Answers 6

6

By using eval() and passing either locals() or any arbitrary dict as the second positional locals argument, you can calculate an f-string dynamically on the fly with any combination of inputs.

def fstr(fstring_text, locals, globals=None):
    """
    Dynamically evaluate the provided fstring_text
    """
    locals = locals or {}
    globals = globals or {}
    ret_val = eval(f'f"{fstring_text}"', locals, globals)
    return ret_val

Sample usage:

format_str = "{i}*{i}={i*i}"
i = 2
fstr(format_str, locals()) # "2*2=4"
i = 4
fstr(format_str, locals()) # "4*4=16"
fstr(format_str, {"i": 12}) # "10*10=100"
Sign up to request clarification or add additional context in comments.

2 Comments

Caution: eval is unsafe, but it WORKS!
avoid the eval and use str.format
5

Use str.format().

Preferably, be explicit about passing arguments to it. But as a stopgap measure, you can use locals() to pass a dict of local (function-defined) variables to the formatting function:

foo = 'bar'
print('Foo is actually {foo}'.format(**locals()))

You can of course copy globals() to a local dict, and merge locals() to it, and use it to more closely emulate the f-string approach.

3 Comments

This isn't equivalent, though may answer this user's question - f'1+2 is {1=2}' returns `'1+2 is 3'. See the answer relating to the string module below.
@SteveHarris: Indeed, not equivalent! You likely don't want to evaluate expressions in strings loaded from a file when all you want is to pretty-print them. Evaluating untrusted input is a security hole.
That's exactly what I was looking for when I found this question. The original equation was specifically about fstrings.
2

you can format it this way. pass in a dictionary of possible values for a and map it to your string.

dictionary = {
  'a':[5,10,15]
}

def func(d):
  for i in range(3):
      print('a is {{a[{0}]}}'.format(i).format_map(d))

func(dictionary)

print:

a is 5
a is 10
a is 15

Comments

2

Here's what you were looking for:

pip install fstring

from fstring import fstring

x = 1

y = 2.0

plus_result = "3.0"

print fstring("{x}+{y}={plus_result}")

# Prints: 1+2.0=3.0

Comments

2

I am surprised why nobody answered with lambda:

foobar = lambda x: f"Foobar is {x}"
foobar(5)
> "Foobar is 5"

Comments

0

Here you go:

In [58]: from functools import partial

In [59]: def func(var_name, a):
    ...:     return var_name + f' is {a}'
    ...:

In [60]: f = partial(func, 'a')

In [61]: f(5)
Out[61]: 'a is 5'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.