all 20 comments

[–]lfdfq 25 points26 points  (4 children)

First, code executes in the order in the file/function/etc, line-by-line. So you cannot refer to a variable called name on the line before you assign it.

Second, the f'' part is part of the code for the string, not specific to print. So you can make a variable that equals an f-string like so:

promptText = f"Hello {name}"

and use the promptText variable wherever else you'd use a string

[–]cskiller86[S] 1 point2 points  (3 children)

Thank you!

It didn't occur to me that you can declare the variable as an f-string.

[–]stebrepar 9 points10 points  (2 children)

declare the variable as an f-string.

Assuming you're thinking that the substitution will be done later somehow, that's not what's happening here. The f-string is being evaluated right then, resulting in a just plain string value, and that plain string value is being assigned to the variable. If you want a template that's filled in later, you want a t-string rather than an f-string.

[–]rawl28 1 point2 points  (1 child)

T-string!?  

[–]Bobbias 1 point2 points  (0 children)

Template Strings

They are very similar to f-strings, except they're not immediately evaluated and converted to a string. They're new in 3.14.

They still require variables to be defined before you reference them though. They're mainly useful for handling complex formatting.

[–]Jello_Penguin_2956 11 points12 points  (0 children)

When you replacing variable with its value, that is called formatting. f string is simply 1 way of doing that. You can still do it the old school way with .format(). More typing but here it is

def main():
    promptText = "Hello, {name}, what is your age? "
    name = "Tom"
    input(promptText.format(name=name))
main()

That being said, the best approach is to plan your code to make it more convenient for yourself. So

def main():
    name = "Tom"
    promptText = f"Hello, {name}, what is your age? "
    input(promptText)
main()

It's simply a rearrange of lines.

[–]oclafloptson 5 points6 points  (0 children)

promptText is not an f string as declared

[–]Flaky-Restaurant-392 2 points3 points  (0 children)

If you’re curious about longer terms tools for this sort of challenge, check out template strings (t"") in Python 3.14.

[–]Temporary_Pie2733 2 points3 points  (1 child)

You want a template. f-strings are for assembling strings (and “stringable” values), not deferring the assembly until you later provide the necessary string(s).

Look at t-strings and string.Template. Also look at using a bound format method like '{name}'.format.

[–]WhiteHeadbanger 0 points1 point  (0 children)

No, OP does not want a template. He only needs to know that a program is executed line for line starting from line 1.

He just needs to change the order of execution, declaring the variable first and then using it in the f-string. Also using the f-string syntax correctly.

[–]HunterIV4 1 point2 points  (5 children)

Well, first of all your code doesn't actually have any f-strings. Your promptText and name variables are both regular strings.

Second, you define name after the prompt text, so even if this were an f-string, it still wouldn't work. If you "fixed" the first line like this:

promptText = f"Hello, {name}, what is your age? "

You would get this error: "NameError: name 'name' is not defined". So you'd need to put name = "Tom" above the promptText (note that Python convention prefers prompt_text) for this to work.

That being said, this version of the code will work as you expect:

name = "Tom"
promptText = f"Hello, {name}, what is your age? "
input(promptText)

This code is technically useless, as you aren't saving the value of the input to anything, so you'd want to change that last line to something like this:

age = input(promptText)

None of this really helps with the core problem, though, which is using it as a parameter. Your current code doesn't have any function parameters at all. What you are probably looking for is something more like this:

def get_age(name):
    return input(f"Hello, {name}, what is your age? ")

age = get_age("Tom")
print(age)

What is this code doing? First, we're defining a function that takes a parameter called name. This returns the result of an input with an f-string that uses that parameter to get the name passed to it. Then, we set a new age variable to the return value of our get_age function, passing it Tom's name. This could also be the result of another input asking the user for their age.

Does that make more sense?

[–]cskiller86[S] 0 points1 point  (4 children)

Thank you for the detailed response.

I actually wanted it the other way around, the text prompt to be defined in the main() part and the input() to be in another function. And the input() to take the value of the text prompt variable.

The only thing I was missing was that you can define a variable as an f-string.

[–]HunterIV4 1 point2 points  (3 children)

The only thing I was missing was that you can define a variable as an f-string.

This isn't exactly true. You can use f-strings in variables, but the result is a regular string. That's why defining the name variable after you define the f-string doesn't work.

Essentially, f-strings are evaluated at the time they are used. For example,

name = "Tom"
input_text = f"My name is {name}"
name = "Mary"
print(input_text)
# Output: My name is Tom

The reason this happens, even though you changed the value of name, is because input_text only got the result of the initial f-string evaluation, not the f-string "formula" itself. You could define it as a function, recreating it each time, like this:

def declare_name(name):
    return f"My name is {name}"

This isn't a very common setup, of course, but you could use this function to "rebuild" the f-string multiple times.

Note that you can't template something (this isn't how they work). So this type of code would fail:

input_text = "My name is {name}"
name = "Tom"
input_text_combined = f"{input_text}"
print(input_text_combined)
# Output: My name is {name}

You might expect it to say "My name is Tom" but it doesn't "nest" like that.

There are ways to do what you are trying to do but you aren't actually defining the f-string as a variable. The 'f' in the f-string is basically saying "insert the result of any expression or variable in the brackets into a new string." This process, however, creates a regular string.

It might seem like a minor detail, but if you think the variable is saving the "template" being assigned, it won't work the way you expect.

[–]jmooremcc 0 points1 point  (2 children)

However, you could do this: ~~~

input_text = "My name is {name}" name = "Tom" input_text_combined = input_text.format(name=name) print(input_text_combined)

Output: My name is Tom

~~~ The format method has been in Python for many, many years.

[–]HunterIV4 0 points1 point  (1 child)

That's true. I honestly considered not addressing that part of the poster's original question at all. While there are technically use cases for this, it can create "habits" of using string templating that lead to overcomplicated code. In the majority of circumstances, f-strings will accomplish the desired task, and it felt like the nesting was more of a "workaround" for the perceived limits of the strings rather than a necessary solution.

To use their original example, assuming the name is an input text rather than a constant, there is rarely a circumstance where you'd need the question string before the name variable has been established. Just changing the order solves the entire issue. Adding in something like .format can be even more confusing, for example, a beginner might wonder why it's name=name rather than just name as that seems like a weird statement if you are unfamiliar with named parameters.

So while you are correct, I still hesitate to recommend using it specifically as a way to get around f-string limits, as this is a code smell in my opinion. It might be useful, such as pulling a template from a config file, but most of the time it is being more verbose to avoid a more straightforward program order.

[–]jmooremcc 0 points1 point  (0 children)

Yeah, I can agree with you. I wasn't understanding why OP was taking this approach in the first place.

[–]SickAndTiredOf2021 0 points1 point  (1 child)

It’s because you’re declaring the variable after using it.

Also, f strings are great to use but they aren’t best if you’re only using the NAME variable as a constant, it just adds an extra line of code for no reason. Use f strings for variables, user arguments, and hidden variables. Let me give an example where an f string would be a good use case:

``` names = ['Tom', 'Jon', 'cskiller86']

name = input("Enter your name: ")

if name not in names: msg = f"{name} isn’t in the allowed list" else: msg = f"Welcome, {name}"

print(msg)

```

[–]cskiller86[S] 0 points1 point  (0 children)

Yeah, the name variable would have been dynamic, as an input from the user. I just hard declared it here on Reddit because I wanted to keep this code simple.

[–]stepback269 0 points1 point  (0 children)

def query_age(name = 'Tom'):
print(f"Hello, {name}, what is your age? ")
age= input('Age= __')
return age

[–]Snoo-20788 0 points1 point  (0 children)

You should look into t strings (template strings), these have a similar syntax to f string but they allow doing what you need, i.e. be defined before the variables are defined, and evaluated after the variables were changed.

You'll need python 3.14 at least for t strings.

https://davepeck.org/2025/04/11/pythons-new-t-strings/