strings inside python template- and f-strings - python

Could someone please break down why "{dic['string_key']}".format(dic=dic) considers the single quotations to be part of the string-key and does a lookup under dic["'string_key'"] ?
a) and b) show the correct way, however I am missing the reason.
a = "{dic[string_key]}"
print(a.format(dic=dic))
b = f"{dic['string_key']}"
print(b)

format and f-strings use braces differently.
With str.format, the contents of the braces are part of a mini-language used by format to substitute its arguments into the format string.
In an f-string, it's an arbitrary Python expression to evaluate.

In this case:
a = "{dic[string_key]}"
print(a.format(dic=dic))
... the string is formatted when .format() is called and that function uses a formatting language that is documented here https://docs.python.org/3/library/string.html#formatstrings.
But in this case:
b = f"{dic['string_key']}"
print(b)
... the string is formatted when the assignment to b is executed, by Python itself. The expression inside the f-string follows normal Python syntax, with the exception that you cannot reuse the quotes used to enclose the f-string.
As a result, you need to specify the quotes around the dictionary key as you would normally, while the mini-language for .format() expects you to omit them.
Also note that this makes a lot of sense: b = f"{dic[string_key]}" should use the value of the variable string_key to index the dictionary.

Related

How to add a string inside an f-string while formatting it in Python?

I was padding an output in a print statement with a simple code which uses .format() function
print('{:-<100}'.format('xyz'))
I was able to get a similar output using f-strings by creating a new variable
library = 'xyz'
print(f'{library:-<100}')
Question: Is there a way to add the string 'xyz' inside the f-string without having to create a new variable?
I tried the code below, but it gave me an error:
print(f'xyz:-<100')
If I understand your question right, then:
You can just use double-qouted string inside single-quoted f-string
print(f'{"xyz":-<100}')
and optional without f-string and format
print("xyz".ljust(100, "-"))
If I'm not mistaken, what you want to do is:
print(f"{'xyz':-<100}") # You can use expressions here, not only variables!
PS: Regarding the error, are you sure you are running Python +3.6?
Yes, there is a way to add the string ('xyz') inside the fstring without having to create a new variable.
Just add the string 'xyz' outside of the curly brackets '{}'
Example:
print(f'xyz{:-<100}')

How to fix SyntaxError: f-string: expressions nested too deeply in python 3.7.0?

Below is my code snippet. When running the code in python 3.7 I get the error SyntaxError: f-string: expressions nested too deeply. How should I refactor my code?
GRAPH_QL_FIELDS = """
cubeId
title
deleted
timeVariableFormat
statisticalProgram {
name
}
topics{
topicId
}
}
"""
query_topics = (
f'query cubesWithTopicLink($deleted: Boolean!, $topicId: String, $first: Int, $skip: Int) {{'
f'dataCubes(where:{AND:[{topics_some: {{topicId: $topicId}}}, {deleted: $deleted}]}, first: $first, skip: $skip) {{'
f'{GRAPH_QL_FIELDS}'
f'dataCubesConnection(where: {topics_some: {topicId: $topicId}})'
f'{{aggregate{{count}}}}'
f'}}'
)
You could use multi-line strings f"""This will work as expected with other nested strings '{3+5}'"""
You cannot nest f-string, like f'{f"my_var"}', so you should refactor your code by removing nested f-string and dividing them into more f-string.
As stated by Dimitris Fasarakis Hilliard:
I don't think formatted string literals allowing nesting (by nesting, I take it to mean f'{f".."}') is a result of careful consideration of possible use cases, I'm more convinced it's just allowed in order for them to conform with their specification.
The specification states that they support full Python expressions* inside brackets. It's also stated that a formatted string literal is really just an expression that is evaluated at run-time (See here, and here). As a result, it only makes sense to allow a formatted string literal as the expression inside another formatted string literal, forbidding it would negate the full support for Python expressions.
The fact that you can't find use cases mentioned in the docs (and only find test cases in the test suite) is because this is probably a nice (side) effect of the implementation and not it's motivating use-case.

Increasing understanding of the formatting in Python with the format() function

hilarious = False
joke_evaluation = "Isn't that joke so funny?! {}"
print(joke_evaluation.format(hilarious))
For the following lines of Python code I'm failing to understand a key concept.
A string is assigned to the variable joke_evaluationand include {} to embed another variable within it.
The third line of code has got me stuck, we are saying print the variable joke_evaluation then using the .format() function and passing another variable to it - hilarious which is set as a boolean data type.
Are the {} effectively functioning as placeholders? How does the .format() function know to populate the {} with the variable hilarious?
Please explain in basic terms if possible to increase my understanding, I'm failing to understand how Python populates the curly braces {} as I've mentioned above.
Here's my understanding of the the format method:
Any string with curly braces {} will be replaced with the variable you have provided. So, if I have a string say:
myStr = "hello {}"
then doing:
res = myStr.format("user")
print(res) #prints "hello user" without quotes.
Now, doing this:
res = myStr.format(123123)
print(res) #prints "hello 123123" without quotes.
As you might have guessed, the integer 123123 was implicitly converted to string before being included in the string.
Now, coming to the curly {} part:
You can have multiple curly braces and must have the same number of parameters passed to format method. Eg:
myStr = "hello {},{},{}, nice meeting you"
res = myStr.format("abcd",123,"lol")
print(res) #prints "hello abcd,123,lol, nice meeting you"
You can even put indices in the {} to indicate position like {0} and {1}.
Yes, {} acting as placeholders, which is treated by .format method in special way.
How does the .format() function know to populate the {} with the variable hilarious?
If you're providing {} only, it's substituted position-wise, i.e.
>>> 'first: {}, second: {}'.format(1, 2)
'first: 1, second: 2'
For more verbose or re-usable substitution you can use named arguments:
>>> "{actor1} tells {actor2} that he's {actor1}".format(actor1='Bob', actor2='Joel')
"Bob tells Joel that he's Bob"
More on awesome string formatting: pyformat.info
A bit more on formatting, when .format substituting placeholders with some objects, it calls __format__ method on it, which
Accepts formatting spec — which gives you ability to control how it will be converted (for example, '{:.2f}'.format(3.1415)
Return str, which will actually substitute placeholders
Read Python documentation about string: https://docs.python.org/3.6/library/string.html?highlight=formatting
:) Everything you need to know. You can also change Python versions and see the behavior of formatting.
Scroll down to see examples and explanations.

Can a variable be passed to format() to pad?

With new-style formatting, we can do:
In [262]: '{:_>10}'.format('test')
Out[262]: '______test'
Instead of the underscore (or whatever character), can this be replaced by a variable? So if:
double_dashes = '--'
Can we somehow incorporate this variable in call to format() so we get:
--------------------test
Instead of the underscore (or whatever character), can this be replaced by a variable?
Yes, that is fairly easy using a nested {}:
>>> '{:{}>10}'.format('test', 'x')
'xxxxxxtest'
Can we somehow incorporate this variable in call to format() so we get:
--------------------test
No. The fill character string must only be one character long.

Explain a python construction

I have a list of tuples in 'tups' and have applied the following code to filter. The list of tuples have the format [(floata,stra1,stra2),(floatb,strb1,strb2),...etc]
keys=sorted({t[2] for t in tups})
for key in keys:
group=filter(lambda t: t[2]==key,tups)
print '{}:\n\tmax: {}\n\tmin: {}'.format(key,max(group),min(group))
Initially I thought the curly brackets was a mistake and changed them to square brackets. I did not get a syntax error but the code did not work. As a last resort I changed the brackets back and everything was fine. Can someone explain the construction. Is this a dictionary comprehension? Where is this explained in the documentation?
If you mean the curly brackets in the first line, this is a set comprehension. This will create a set of the third item from every tuple in tups. A set is similar to a list, but without order, and therefore cannot contain duplicates.
If you mean the brackets in the string, this is just new-style string formatting. Calling str.format() changes those braces into the passed values.
Before Python 2.6, you would have used:
print '%s:\n\tmax: %s\n\tmin: %s' % (key,max(group),min(group))
to format a string using placeholders (the %s).
Since Python 2.6, you can use the {} syntax for the placeholder and .format instead:
print '{}:\n\tmax: {}\n\tmin: {}'.format(key,max(group),min(group))
or using positional arguments:
print '{0}:\n\tmax: {2}\n\tmin: {1}'.format(key,min(group),max(group))
(notice that I changed the order of the arguments, but the output is the same: we used {2} to represent the third argument...)
Just an advice: when you get a lot of arguments, it's easier to name them, as:
print '{key}:\n\tmax: {groupmax}\n\tmin: {groupmin}'.format(key=key,groupmin=min(group),groupmax=max(group))
The .format syntax is more powerful than the % one: examples are available in the documentation.

Categories