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 OverflowWhy does Python `f-string` + inline for loop create a generator when they're passed as parameter? - Stack Overflow
python - F string inside For Loop - Stack Overflow
`str.join(str(i) for i in value)` for `f-strings` - Python Discussions
Why do people use .format() method when f string literal exists?
Videos
While you have a loop, you also have a return inside the loop. On the first iteration of the list this return will be hit and execution of the function will stop there, returning only value on that line — which is a string — rather than the list intended.
You either need to add a list to the function to use as an accumulator before returning —
def names_function(lst):
names = []
for name in lst:
names.append(f"{name['first']} {name['last']}")
return names
Or to use a list comprehension
def names_function(lst):
return [f"{name['first']} {name['last']}" for name in lst]
names_function(names)
Both will output
['John Smith', 'Jessie Snow']
You could also replace the return with a yield to turn this into a generator. To get all the values you would need to iterate the generator (or call list on it)
def names_function(lst):
for name in lst:
yield f"{name['first']} {name['last']}"
list(names_function(names))
Which gives the same result
['John Smith', 'Jessie Snow']
if you wantto get all names:
def names_function(lst):
ret=""
for name in lst:
ret += f"{name['first']} {name['last']}\n"
return ret
or
def names_function(lst):
return [f"{name['first']} {name['last']}" for name in lst]
if you want to create a generator object:
def names_function(lst):
return (f"{name['first']} {name['last']}" for name in lst)
The looping construct you're using is a generator expression. To write one as a stand-alone expression, you need to add parentheses around it:
genexp = (f"{s}" for s in ["bar"])
If the generator expression is the only argument to a function, you don't need double parentheses (but you do if there are other separate arguments). Contrast:
s = sum(i % 2 for i in some_sequence) # count of odd elements, no extra parentheses needed
vs:
print(*(i for i in some_sequence if i % 2), sep=",") # print odds, parens are needed this time
There's nothing special about f-string used in the generator expression in your code, any expression works the same way.
These are examples of generator expressions and don't necessarily have anything specific to f-strings or which functions you use with them.
e.g.
>>> x = [1, 2, 3, 4]
>>> sum(i%2==0 for i in x)
2
The example counts the number of even integers in the list.
You can read more about them here: https://dbader.org/blog/python-generator-expressions
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!