Which one? f string or using format in python3 - python

Which one is better in python3?
They have same output but most of codes are using format instead F string.
a = "Test"
print(f"this is for {a}")
or format?
print("This is for {}".format(a))
Some times when I used F string for Directory and file path I got some errors but there
were no problem with using format.

As pointed out in the comments, a good comparison of string formatting methods is provided on the Real Python website.
f-strings in many situations can be more readable and less human-error prone to code than other variants, but require Python >= 3.6, so may have to be avoided if backwards compatibility is required. In general they are a good choice though, up to a few gotchas that come up from time to time.
When nesting f-strings you have to be careful with quotation marks. This fails:
>>> f"Hello {"there"}"
File "<stdin>", line 1
f"Hello {"there"}"
^
SyntaxError: invalid syntax
But using other quotation marks on the inside lets you get around this:
>>> f"Hello {'there'}"
'Hello there'
You cannot nest f-strings containing string literals deeper than that though, because you have no further different quotation marks to use.
Another gotcha I stumble across regularly is the restriction on not allowing backslashes in the f-string expression part, even if they are inside a string literal:
>>> f"Path: {'C:\Windows'}"
File "<stdin>", line 1
SyntaxError: f-string expression part cannot include a backslash
You can get around that using an intermediate variable, or format():
>>> path = 'C:\Windows'
>>> f"Path: {path}"
'Path: C:\\Windows'
>>> "Path: {0}".format('C:\Windows')
'Path: C:\\Windows'
This is probably the issue you had with using f-strings to format paths. I personally tend to encounter this limitation when working with string literals that have newlines '\n' in them inside the f-string expression part.

Related

What does = (equal) do in f-strings inside the expression curly brackets?

The usage of {} in Python f-strings is well known to execute pieces of code and give the result in string format (some tutorials here). However, what does the '=' at the end of the expression mean?
log_file = open("log_aug_19.txt", "w")
console_error = '...stuff...' # the real code generates it with regex
log_file.write(f'{console_error=}')
This is actually a brand-new feature as of Python 3.8.
Added an = specifier to f-strings. An f-string such as f'{expr=}'
will expand to the text of the expression, an equal sign, then the
representation of the evaluated expression.
Essentially, it facilitates the frequent use-case of print-debugging, so, whereas we would normally have to write:
f"some_var={some_var}"
we can now write:
f"{some_var=}"
So, as a demonstration, using a shiny-new Python 3.8.0 REPL:
>>> print(f"{foo=}")
foo=42
>>>
From Python 3.8, f-strings support "self-documenting expressions", mostly for print de-bugging. From the docs:
Added an = specifier to f-strings. An f-string such as f'{expr=}' will
expand to the text of the expression, an equal sign, then the
representation of the evaluated expression. For example:
user = 'eric_idle'
member_since = date(1975, 7, 31)
f'{user=} {member_since=}'
"user='eric_idle' member_since=datetime.date(1975, 7, 31)"
The usual f-string format specifiers allow more control over how the
result of the expression is displayed:
>>> delta = date.today() - member_since
>>> f'{user=!s} {delta.days=:,d}'
'user=eric_idle delta.days=16,075'
The = specifier will display the whole expression so that calculations
can be shown:
>>> print(f'{theta=} {cos(radians(theta))=:.3f}')
theta=30 cos(radians(theta))=0.866
This was introduced in python 3.8. It helps reduce a lot of f'expr = {expr} while writing codes. You can check the docs at What's new in Python 3.8.
A nice example was shown by Raymond Hettinger in his tweet:
>>> from math import radians, sin
>>> for angle in range(360):
print(f'{angle=}\N{degree sign} {(theta:=radians(angle))=:.3f}')
angle=0° (theta:=radians(angle))=0.000
angle=1° (theta:=radians(angle))=0.017
angle=2° (theta:=radians(angle))=0.035
angle=3° (theta:=radians(angle))=0.052
angle=4° (theta:=radians(angle))=0.070
angle=5° (theta:=radians(angle))=0.087
angle=6° (theta:=radians(angle))=0.105
angle=7° (theta:=radians(angle))=0.122
angle=8° (theta:=radians(angle))=0.140
angle=9° (theta:=radians(angle))=0.157
angle=10° (theta:=radians(angle))=0.175
...
You can also check out this to get the underlying idea on why this was proposed in the first place.
As mention here:
Equals signs are now allowed inside f-strings starting with Python 3.8. This lets you quickly evaluate an expression while outputting the expression that was evaluated. It's very handy for debugging.:
It mean it will run the execution of the code in the f-string braces, and add the result at the end with the equals sign.
So it virtually means:
"something={executed something}"
f'{a_string=}' is not exactly the same as f'a_string={a_string}'
The former escapes special characters while the latter does not.
e.g:
a_string = 'word 1 tab \t double quote \\" last words'
print(f'a_string={a_string}')
print(f'{a_string=}')
gets:
a_string=word 1 tab double quote \" last words
a_string='word 1 tab \t double quote \\" last words
I just realised that the difference is that the latter is printing the repr while the former is just printing the value. So, it would be more accurate to say:
f'{a_string=}' is the same as f'a_string={a_string!r}'
and allows formatting specifications.

Why isn't it possible to use backslashes inside the braces of f-strings? How can I work around the problem? [duplicate]

This question already has answers here:
How can I use newline '\n' in an f-string to format output?
(7 answers)
Closed last month.
In Python >=3.6, f-strings can be used as a replacement for the str.format method. As a simple example, these are equivalent:
'{} {}'.format(2+2, "hey")
f'{2+2} {"hey"}'
Disregarding format specifiers, I can basically move the positional arguments of str.format inside braces in an f-string. Note specifically that I am allowed to just put str literals in here, although it may seem a bit unwieldy.
There are however some limitations. Specifically, backslashes in any shape or form are disallowed inside the braces of an f-string:
'{}'.format("new\nline") # legal
f'{"new\nline"}' # illegal
f'{"\\"}' # illegal
I cannot even use \ to split up a long line if it's inside the braces;
f'{2+\
2}' # illegal
even though this usage of \ is perfectly allowed inside normal str's;
'{\
}'.format(2+2) # legal
It seems to me that a hard stop is coded into the parser if it sees the \ character at all inside the braces of an f-string. Why is this limitation implemented? Though the docs specify this behavior, it does not justify why.
You seem to expect
'{}'.format("new\nline")
and
f'{"new\nline"}'
to be equivalent. That's not what I would expect, and it's not how backslashes in f-strings worked back in the pre-release versions of Python 3.6 where backslashes between the braces were allowed. Back then, you'd get an error because
"new
line"
is not a valid Python expression.
As just demonstrated, backslashes in the braces are confusing and ambiguous, and they were banned to avoid confusion:
The point of this is to disallow convoluted code like:
>>> d = {'a': 4}
>>> f'{d[\'a\']}'
'4'
In addition, I'll disallow escapes to be used for brackets, as in:
>>> f'\x7bd["a"]}'
'4'
(where chr(0x7b) == "{").
It's annoying that you can't do this:
things = ['Thing one','Thing two','Thing three']
print(f"I have a list of things: \n{'\n'.join(things)}")
But you can do this:
things = ['Thing one','Thing two','Thing three']
nl = '\n'
print(f"I have a list of things:\n{nl.join(things)}")
For new lines, you can use os.linesep instead of \n. For example:
>>> import os
>>>
>>> print(f"Numbers:\n{os.linesep.join(map(str, [10, 20, 30]))}")
Numbers:
10
20
30
I am not sure if this helps, but instead of the illegal
f'{"new\nline"}'
one could use
f'{"new"+chr(10)+"line"}'

In Python 3.6, why don't string literals (using the same quote type) work inside interpolated strings?

Basic example:
>>> table = {'username': 'John Doe'}
>>> msg = f'Hello {table['username']}'
File "<stdin>", line 1
msg = f'Hello {table['username']}'
^
SyntaxError: invalid syntax
>>> msg = f"Hello {table['username']}"
Why doesn't it work when both the format string and the inner string literal use the same quote type (both single-quoted or double-quoted)? Is this a bug in Python 3.6, or is this intentional?
edit: To make it clear why I'm asking this, something like this works fine in C#:
using System;
public static class Program {
public static void Main() {
Console.WriteLine($"Hello {"world"}");
}
}
Proof
This has nothing to do with interpolated strings. An interpolated string is read the same as any other string literal* and then interpolated, and you can't put unescaped quote characters in the middle of any string:
>>> msg = 'Hello {table['username']}'
File "<stdin>", line 1
'Hello {table['username']}'
^
SyntaxError: invalid syntax
>>> msg = 'Hello 'world''
File "<stdin>", line 1
msg = 'Hello 'world''
^
SyntaxError: invalid syntax
This is exactly why we have a choice of two different quote characters—and, when that isn't enough, triple-quoted strings. And of course escaping.
So, why can't Python be smarter here? Think about what "smarter" would mean. Assuming it can't read your mind, it would have to parse every possible way that pairs of quotes could be matched up if some of them were skipped and then figure out which one made for a valid result. That might not seem too bad for a simple one-liner at the interactive interpreter, but if it had to do that across an entire file, every time you run a non-trivial script or import a module with more than a few quotes in it, it would take minutes to try all the parses, and the result could well be ambiguous anyway.
Could they instead add special rules for handling quotes only in interpolated strings, only inside currently-open braces (but not double braces, of course, because those are escapes), and so on?
Sure, That wouldn't make the parser exponential, just more complicated. But more complicated is not good either.
The fact that Python has a simple set of rules that anyone can knock out a LL(1) implementation of—and, maybe even more importantly, that anyone can keep in their heads and work through—is a major feature of the language as compared to, say, C++. So every time there's a tradeoff between nice syntactic sugar vs. keeping the parser simple, it has to be thought through, and the answer is always keeping the parser simpler. In fact, this was an explicit decision in the Python 3 transition:
Simple is better than complex. This idea extends to the parser. Restricting Python's grammar to an LL(1) parser is a blessing, not a curse. It puts us in handcuffs that prevent us from going overboard and ending up with funky grammar rules like some other dynamic languages that will go unnamed, such as Perl.
Also, of course, that would be a difference between f-strings and str.format, which would be another rule to learn, and to relearn every time you come back to Python after a few months away. Which is a different rule from the Zen: Special cases aren't special enough to break the rules.
the problem is that it is a string and you did not do the interpolation, because that was the error, you should use string.Template to define a format string or you can use the format method of str class with which you can substitute values inside of a String
'Hello {table['username']}' this is bad
you can use 'Hello {username}'.format(username=table['username'])
see for more information: here

How can I print a string using .format(), and print literal curly brackets around my replaced string [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How can I print a literal “{}” characters in python string and also use .format on it?
Basically, I want to use .format(), like this:
my_string = '{{0}:{1}}'.format('hello', 'bonjour')
And have it match:
my_string = '{hello:bonjour}' #this is a string with literal curly brackets
However, the first piece of code gives me an error.
The curly brackets are important, because I'm using Python to communicate with a piece of software via text-based commands. I have no control over what kind of formatting the fosoftware expects, so it's crucial that I sort out all the formatting on my end. It uses curly brackets around strings to ensure that spaces in the strings are interpreted as single strings, rather than multiple arguments — much like you normally do with quotation marks in file paths, for example.
I'm currently using the older method:
my_string = '{%s:%s}' % ('hello', 'bonjour')
Which certainly works, but .format() seems easier to read, and when I'm sending commands with five or more variables all in one string, then readability becomes a significant issue.
Thanks!
Here is the new style:
>>> '{{{0}:{1}}}'.format('hello', 'bonjour')
'{hello:bonjour}'
But I thinking escaping is somewhat hard to read, so I prefer to switch back to the older style to avoid escaping:
>>> '{%s:%s}' % ('hello', 'bonjour')
'{hello:bonjour}'

How to write string literals in Python without having to escape them?

Is there a way to declare a string variable in Python such that everything inside of it is automatically escaped, or has its literal character value?
I'm not asking how to escape the quotes with slashes, that's obvious. What I'm asking for is a general purpose way for making everything in a string literal so that I don't have to manually go through and escape everything for very large strings.
Raw string literals:
>>> r'abc\dev\t'
'abc\\dev\\t'
If you're dealing with very large strings, specifically multiline strings, be aware of the triple-quote syntax:
a = r"""This is a multiline string
with more than one line
in the source code."""
There is no such thing. It looks like you want something like "here documents" in Perl and the shells, but Python doesn't have that.
Using raw strings or multiline strings only means that there are fewer things to worry about. If you use a raw string then you still have to work around a terminal "\" and with any string solution you'll have to worry about the closing ", ', ''' or """ if it is included in your data.
That is, there's no way to have the string
' ''' """ " \
properly stored in any Python string literal without internal escaping of some sort.
You will find Python's string literal documentation here:
http://docs.python.org/tutorial/introduction.html#strings
and here:
http://docs.python.org/reference/lexical_analysis.html#literals
The simplest example would be using the 'r' prefix:
ss = r'Hello\nWorld'
print(ss)
Hello\nWorld
(Assuming you are not required to input the string from directly within Python code)
to get around the Issue Andrew Dalke pointed out, simply type the literal string into a text file and then use this;
input_ = '/directory_of_text_file/your_text_file.txt'
input_open = open(input_,'r+')
input_string = input_open.read()
print input_string
This will print the literal text of whatever is in the text file, even if it is;
' ''' """ “ \
Not fun or optimal, but can be useful, especially if you have 3 pages of code that would’ve needed character escaping.
Use print and repr:
>>> s = '\tgherkin\n'
>>> s
'\tgherkin\n'
>>> print(s)
gherkin
>>> repr(s)
"'\\tgherkin\\n'"
# print(repr(..)) gets literal
>>> print(repr(s))
'\tgherkin\n'
>>> repr('\tgherkin\n')
"'\\tgherkin\\n'"
>>> print('\tgherkin\n')
gherkin
>>> print(repr('\tgherkin\n'))
'\tgherkin\n'

Categories