I would like to create an f-string that could be used multiple times as the following code with format
:
TEXT_AMOUNT = 'text {amount}'
def f1(beginning):
return beginning + TEXT_AMOUNT.format(amount=10)
def f2(ending):
return TEXT_AMOUNT.format(amount=100) + ending
How can I achieve the same functionality with using an f-string? I tried:
TEXT_AMOUNT = f'text {amount}'
def f1(beginning):
amount = 100
return beginning + TEXT_AMOUNT
def f2(ending):
amount = 10
return TEXT_AMOUNT + ending
However, I get the following error:
NameError: name 'amount' is not defined
You can't.
An f-string isn't a kind of string, it's a kind of string literal, which is evaluated immediately. You can't store an f-string in a variable to be evaluated later, or accept one from a user, etc.1 This is the only reason that they're safe.
So, what if you do want to use a format multiple times (or one taken from a user, etc.)? You use str.format
.
Occasionally, you need to capture all of the locals and globals the same way an f-string does, but to do it explicitly. Because this is a rare case (and potentially a security hole), it's intentionally a bit ugly:
TEXT_AMOUNT = 'text {amount}'
def f1(beginning):
amount = 100
return beginning + TEXT_AMOUNT.format(**locals(), **globals())
This makes you think about what you're writing—you don't really want globals
here, right? So leave it off. And it also signals the reader—if you're pulling in locals
, they'll want to see that the string really is a constant in your source that isn't doing anything dangerous.
1. Well, you could use an f-string inside a string that you pass to eval
… but that's a terrible idea.