Both ternaries ("if expressions") and comprehensions ("for expressions") are allowed inside f-strings. However, they must be part of expressions that evaluate to strings. For example, key: value is a dict pair, and f"{key}: {value}" is required to produce a string.
>>> dct = {'a': 1, 'b': 2}
>>> newline = "\n" # \escapes are not allowed inside f-strings
>>> print(f'{newline.join(f"{key}: {value}" for key, value in dct.items())}')
a: 1
b: 2
Note that if the entire f-string is a single format expression, it is simpler to just evaluate the expression directly.
>>> print("\n".join(f"{key}: {value}" for key, value in dct.items())))
a: 1
b: 2
Expressions inside format strings still follow their regular semantics. For example, a ternary may test whether an existing name is true. It will fail if the name is not defined.
>>> c, name = "Hello", ""
>>> f'{c} {name if name else "unknown"}'
'Hello unknown'
>>> del name
>>> f'{c} {name if name else "unknown"}'
NameError: name 'name' is not defined
Answer from MisterMiyagi on Stack OverflowVideos
just thought id make a post incase anyone has an issue using f-string with a list. i moved on from using .format() to using f-string. i have found it pretty easy to get adjusted to but i was struggling with using specific values within a list, i treid a few methods like:
names = ['Adam', 'Bob', 'Cyril']
text = f'Winners are: {0} {1} {2}'(*names)
print(text)
names = ['Adam', 'Bob', 'Cyril']
text = f'Winners are: {*0} {*1} {*2}'(names)
print(text)
names = ['Adam', 'Bob', 'Cyril']
text = f'Winners are: {[0]} {[1]} {[2]}'(names)
print(text)
all came back with errors and left me stuck on how to use f-string with a list until i watched Corey Schafers video, within the half an hour i was pretty much trying to brute force it, reaching the same error, i found out the correct way of interlopoing a list with a f-string is:
names = ['Adam', 'Bob', 'Cyril']
text = f'Winners are: {names[0]}, {names[1]}, {names[2]}'
print(text)
just thought id make the post incase anyone else is unsure on how.
Hello all,
I seem to encounter a lot of documentation and tutorials that use .format() method instead of f string literals.
Personally,
print("I can't seem to {} of a {} why someone {} {} {}".format('think', 'reason', 'would', 'prefer', 'this'))versus
easily = "easily"
sentence = "sentence"
this = "this"
print(f"A much more {easily} readable {sentence} such as {this}")F string literal is always much easier to decipher and thus avoid errors.
Perhaps there's some benefit of .format() that I'm unaware of. Googling hasn't brought up much on the debate.
Cheers!
I was trying to make a, silly program in which you can do some random things. I used arguments (%)in the past, but it's a bit hard to write like the identification of the variable, like there is so much types (%s, %f, %2f, %d, %g, %e...) and I want to take the easiest to write or the easiest to debug.
here are some examples of using each one:
using (%):
name = "Imaginary_Morning"
age = 13
print("This profile is called %s and it has %d years old." % (name, age))
using (f"string"):
name = "Imaginary_Morning"
age = 13
print(f"This profile is called {name} and it has {age} years old.")
using (.format()):
name = "Imaginary_Morning"
age = 13
print("This profile is called {} and it has {} years old.".format(name, age))I'm afraid that it will be deprecated during the next Python versions
Don't be, str.format does not appear (nor has a reason) to be leaving any time soon, the PEP that introduced fprefixed-strings even states in its Abstract:
This PEP does not propose to remove or deprecate any of the existing string formatting mechanisms.
Formatted strings were introduced to address some of the shortcomings other methods for formatting strings had; not to throw the old methods away and force god-knows how many projects to use f-string's if they want their code to work for Python 3.6+.
As for the performance of these, it seems my initial suspicion that they might be slower is wrong, f-strings seem to easily outperform their .format counterparts:
➜ cpython git:(master) ./python -m timeit -s "a = 'test'" "f'formatting a string {a}'"
500000 loops, best of 5: 628 nsec per loop
➜ cpython git:(master) ./python -m timeit "'formatting a string {a}'.format(a='test')"
100000 loops, best of 5: 2.03 usec per loop
These were done against the master branch of the CPython repository as of this writing; they are definitely subject to change:
f-strings, as a new feature, might have possible optimizations- Optimizations to CPython might make
.formatfaster (e.g Speedup method calls 1.2x)
But really, don't worry about speed so much, worry about what is more readable to you and to others.
In many cases, that's going to be f-strings, but there's some cases where format is better.
To build on Jim's answer and address your performance concern, I used python's dis module to compare the bytecode instructions for two syntactically different, but functionally equivalent functions.
import dis
def f1():
a = "test"
return f"{a}"
def f2():
return "{a}".format(a='test')
print(dis.dis(f1))
print(dis.dis(f2))
The result of which is:
11 0 LOAD_CONST 1 ('test')
2 STORE_FAST 0 (a)
12 4 LOAD_FAST 0 (a)
6 FORMAT_VALUE 0
8 RETURN_VALUE
None
15 0 LOAD_CONST 1 ('{a}')
2 LOAD_ATTR 0 (format)
4 LOAD_CONST 2 ('test')
6 LOAD_CONST 3 (('a',))
8 CALL_FUNCTION_KW 1
10 RETURN_VALUE
None
One can see that the f-string handles the formatting without attribute or function calls, which can impose type checking and memory overhead. According to timeit this results in a roughly 3x performance gain (for my specific functions)
>>> timeit.timeit('f1()', 'from __main__ import f1', number=100000)
0.012325852433775708
>>> timeit.timeit('f2()', 'from __main__ import f2', number=100000)
0.036395029920726074