Search code examples
pythonpython-3.xf-string

Is it possible to reuse an f-string as it is possible with a string and format?


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

Solution

  • 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.