Posts: 212
Threads: 25
Joined: Aug 2019
Sep-16-2019, 02:46 AM
(This post was last modified: Sep-16-2019, 02:46 AM by newbieAuggie2019.)
Hi!
I knew nothing about f-strings until on this site somebody suggested them as a more appropriate and straightforward way to print strings. The books I was using didn't say anything about them, as f-strings appeared with Python 3.6. Such is the case, that even in books printed in 2018 and 2019, you are lucky if more than a paragraph is dedicated to them!!!
So I looked for sites on the internet, and I found more information. I did even write a couple of simple programs comparing the printing time for strings printed with the %-format, strings printed with the .format() type, and f-strings. The f-string formatting seems to be the fastest, at least when the strings are simple. The second place is for %-formatted strings, which is curious, as they seem to be deprecated in the near future. I think I read it's due to some collateral problems... Not sure which ones...
Then, I decided to complicate things a bit more, with multiline strings with even lines in blank, like citing a few quotes attributed to somebody. While I had no problems at printing them, I encountered problems at trying to time them (I tried different functions from different modules, with similar problems). It seems that then, f-strings is not very new line (\n) friendly, and although I tried some suggestions I found, they didn't work. They were too many quotation marks; I tried adding quotation marks used in other languages, but it was of no use either. I tried using strings as a concatenation of strings, I tried also to make one of those concatenated strings equal to "\n", but neither of them managed to work...
So, my questions are:
1) When it's better not to use f-strings?
2) As my purpose was to compare the printing time for complex strings formatted differently, is there a way to do it, or it cannot be used for f-strings?
All the best,
newbieAuggie2019
"That's been one of my mantras - focus and simplicity. Simple can be harder than complex: You have to work hard to get your thinking clean to make it simple. But it's worth it in the end because once you get there, you can move mountains."
Steve Jobs
Posts: 4,795
Threads: 76
Joined: Jan 2018
This is not really an answer, but don't forget that templating systems also exist for "complex" string formatting, such as Mako templates. For me, fstrings are only designed for simple string interpolations, in the same category as format() or %.
Posts: 1,950
Threads: 8
Joined: Jun 2018
There is website with examples dedicated to show differences in possibilities of % and .format method: PyFormat: Using % and .format() for great good!. No f-strings but I believe it can be source of some ideas.
I approach string formatting this way: start with f-strings. If it seems too complicated or non-pythonic then fall back to .format.
f-strings are 'not \ friendly' i.e. one cannot use escaping in placeholders.
Regarding speed. One can test it, on my machine I get this:
In [122]: timeit.timeit("""name = 'Internet'
...: age = 30
...: '%s is %s' % (name, age)""", number = 100000)
Out[122]: 0.03204629699757788
In [123]: timeit.timeit("""name = 'Internet'
...: age = 30
...: '{} is {}'.format(name, age)""", number = 100000)
Out[123]: 0.04341071600356372
In [124]: timeit.timeit("""name = 'Internet'
...: age = 30
...: '{name} is {age}'""", number = 100000)
Out[124]: 0.002835419996699784 At the beginning f-string were slower than .format but this was fixed ( Make f'' strings faster than .format: BUILD_STRING opcode?)
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy
Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Posts: 8,163
Threads: 160
Joined: Sep 2016
Sep-16-2019, 06:09 AM
(This post was last modified: Sep-16-2019, 06:09 AM by buran.)
just to mention that if there is need for escaping within placeholder than it's a case of having expression IN the placeholder. In this case it would be better and more readable to have the expression prepared and assigned to a variable beforehand and use that variable in the f-string
I would prefer f-strings over .format or % in any case
Of course there are cases where using template engine is warranted or like in SQL statements where you should not use string formatting with untrusted input
Posts: 1,950
Threads: 8
Joined: Jun 2018
(Sep-16-2019, 06:09 AM)buran Wrote: just to mention that if there is need for escaping within placeholder than it's a case of having expression IN the placeholder. In this case it would be better and more readable to have the expression prepared and assigned to a variable beforehand and use that variable in the f-string
To showcase buran's suggestion:
>>> newline = '\n'
>>> first = 'first'
>>> second = 'second'
>>> print(f'{first}{newline}{second}')
first
second
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy
Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Posts: 212
Threads: 25
Joined: Aug 2019
Sep-16-2019, 06:31 AM
(This post was last modified: Sep-16-2019, 06:48 AM by newbieAuggie2019.)
(Sep-16-2019, 04:54 AM)Gribouillis Wrote: This is not really an answer, but don't forget that templating systems also exist for "complex" string formatting, such as Mako templates. For me, fstrings are only designed for simple string interpolations, in the same category as format() or %. Hi!
Thank you for your answer. I didn't know about Mako templates (as I don't know many other things in Python  ).
I checked and it seems that it is used by reddit.com, for example.
The problem is that I'm just starting, and it uses classes, something that I don't know how to use yet. But I don't have problems printing complex f-string formatting. I DO have problems when trying to time the printing of that complex f-string.
For instance, for very simple strings:
import timeit
integer1 = 25
string1 = 'TWENTY-FIVE'
setup = """
integer1 = 25
string1 = 'TWENTY-FIVE'
""".strip()
print('\nString number %s, or simply %d' % (string1, integer1))
print('String number {}, or simply {}'.format(string1, integer1))
print(f'String number {string1}, or simply {integer1}')
percent_stmt = "'String number %s, or simply %d' % (string1, integer1)"
call_stmt = "'String number {}, or simply {}'.format(string1, integer1)"
fstr_stmt = """f'String number {string1}, or simply {integer1}'"""
def time(stmt):
return f"{timeit.timeit(stmt, setup, number=int(1e4)):.5f}"
print(f"\nThe printing times of the different formatting types are:\n")
print(f"Timing percent formating: {time(percent_stmt)}s" )
print(f"Timing call formating: {time(call_stmt)}s")
print(f"Timing f-string formating: {time(fstr_stmt)}s\n") and that produced on one of the occasions, the following ouput:
Output: String number TWENTY-FIVE, or simply 25
String number TWENTY-FIVE, or simply 25
String number TWENTY-FIVE, or simply 25
The printing times of the different formatting types are:
Timing percent formating: 0.00296s
Timing call formating: 0.00333s
Timing f-string formating: 0.00147s
or even with a bit longer strings:
import timeit
name = "Arnold Schwarzenegger"
age = 72
print("\n\nThis is printing strings with %-formatting (not recommended by the Python docs):")
print('%s is %s.' % (name, age))
t1 = timeit.timeit("""name = "Arnold Schwarzenegger"
age = 72
'%s is %s.' % (name, age)""", number = 10000)
print("That took", t1, end='s to print.')
print("\n\nThis is printing strings with str.format():")
print('{} is {}.'.format(name, age))
t2 = timeit.timeit("""name = "Arnold Schwarzenegger"
age = 72
'{} is {}.'.format(name, age)""", number = 10000)
print("That took", t2, end='s to print.')
print("\n\nThis is printing strings with f-formatting:")
print(f'{name} is {age}.')
t3 = timeit.timeit("""name = "Arnold Schwarzenegger"
age = 72
f'{name} is {age}.'""", number = 10000)
print("That took", t3, end='s to print.\n')
print(f"""
It seems that {t3}s (f-formatting) is < {t1}s (%-formatting)
(%-formatting is not recommended by the Python docs).
It seems also that {t3}s (f-formatting) is < {t2}s (str.format()).
So it appears clearly that F-FORMATTING IS INDEED THE FASTEST WAY TO PRINT STRINGS.
""") which in one of the instances, produced this output:
Output: This is printing strings with %-formatting (not recommended by the Python docs):
Arnold Schwarzenegger is 72.
That took 0.0026088639999999885s to print.
This is printing strings with str.format():
Arnold Schwarzenegger is 72.
That took 0.00298629899999997s to print.
This is printing strings with f-formatting:
Arnold Schwarzenegger is 72.
That took 0.0014626989999999562s to print.
It seems that 0.0014626989999999562s (f-formatting) is < 0.0026088639999999885s (%-formatting)
(%-formatting is not recommended by the Python docs).
It seems also that 0.0014626989999999562s (f-formatting) is < 0.00298629899999997s (str.format()).
So it appears clearly that F-FORMATTING IS INDEED THE FASTEST WAY TO PRINT STRINGS.
but when the strings are more complex, even not having problems at printing them, I'm having problems at timing the printing of those examples.
(Sep-16-2019, 04:54 AM)Gribouillis Wrote: For me, fstrings are only designed for simple string interpolations, in the same category as format() or %. I was trying to find out where I saw that %-formatting is going to be deprecated (I thought it was in the Python docs, but I cannot find it now, although they referred to it, as the old %-formatting).
All the best,
(Sep-16-2019, 06:20 AM)perfringo Wrote: (Sep-16-2019, 06:09 AM)buran Wrote: just to mention that if there is need for escaping within placeholder than it's a case of having expression IN the placeholder. In this case it would be better and more readable to have the expression prepared and assigned to a variable beforehand and use that variable in the f-string
To showcase buran's suggestion:
>>> newline = '\n'
>>> first = 'first'
>>> second = 'second'
>>> print(f'{first}{newline}{second}')
first
second Thank you to both of you, Buran and Perfringo!
What I meant is this, by modifying your program:
import timeit
newline = '\n'
first = 'first'
second = 'second'
print("\n\nThis is printing strings with f-formatting:")
print(f'{first}{newline}{second}')
t3 = timeit.timeit("""newline = '\n'
first = 'first'
second = 'second'
f'{first}{newline}{second}'""", number = 10000)
print("That took", t3, end='s to print.\n') And when I run it, I have this output with an error message:
Output: This is printing strings with f-formatting:
first
second
Error: Traceback (most recent call last):
File "C:/Users/User1/AppData/Local/Programs/Python/Python37/compare_speed_strings_03.py", line 15, in <module>
f'{first}{newline}{second}'""", number = 10000)
File "C:\Users\User1\AppData\Local\Programs\Python\Python37\lib\timeit.py", line 232, in timeit
return Timer(stmt, setup, timer, globals).timeit(number)
File "C:\Users\User1\AppData\Local\Programs\Python\Python37\lib\timeit.py", line 121, in __init__
compile(stmtprefix + stmt, dummy_src_name, "exec")
File "<timeit-src>", line 2
newline = '
^
SyntaxError: EOL while scanning string literal
1) Is it something that I'm doing wrong? (with my other example programs that I attached in my previous posts, I didn't have problems)
2) Is it something with f-strings and newlines to be timed? (no problems to print)
All the best,
newbieAuggie2019
"That's been one of my mantras - focus and simplicity. Simple can be harder than complex: You have to work hard to get your thinking clean to make it simple. But it's worth it in the end because once you get there, you can move mountains."
Steve Jobs
Posts: 7,320
Threads: 123
Joined: Sep 2016
Sep-16-2019, 08:54 AM
(This post was last modified: Sep-16-2019, 09:03 AM by snippsat.)
I use only f-string for string formatting now,and have done so for a while(years).
They are more readable,more concise,and less prone to error than other ways of formatting,they are also faster!.
For me is very simple to see this.
>>> name = "Kent"
>>> age = 30
# The expressions is in the string where the belong
>>> print(f"Hello, {name}. You are {age}.")
Hello, Kent. You are 30.
# The expressions is behind and not where the should be,and only {} in string
>>> print("Hello, {}. You are {}.".format(name, age))
Hello, Kent. You are 30. (Sep-16-2019, 06:31 AM)newbieAuggie2019 Wrote: 2) Is it something with f-strings and newlines to be timed? (no problems to print) Don't pack in a string,use a function.
There is no need to measure,they are faster.
import timeit
def run_me():
newline = '\n'
first = 'first'
second = 'second'
"\n\nThis is printing strings with f-formatting:"
f'{first}{newline}{second}'
#'{}{}{}'.format(first, newline, second)
print(timeit.Timer("run_me()",'from __main__ import run_me').timeit(number=10000000)) Output: f-string: 3.2901052
.format(): 6.3253624
Posts: 2,128
Threads: 11
Joined: May 2017
Sep-16-2019, 08:54 AM
(This post was last modified: Sep-16-2019, 08:55 AM by DeaD_EyE.)
In line 8 a r in front of the quote.
This suppresses the interpretation of \n .
Otherwise \n is replaced with a newline.
The r comes from regex. This type of string is called regex-string.
If you use regex, you have many backslashes and some of them change the meaning, if a character comes after.
For example:
To prevent interpretation in regular strings, you can use double backslash.
text1 = "Text with\nline break"
text2 = "Text without\\nline break"
text3 = "Text with \"Quotes\""
print(text1, text2, text3, sep='\n') import timeit
newline = '\n'
first = 'first'
second = 'second'
print("\n\nThis is printing strings with f-formatting:")
print(f'{first}{newline}{second}')
t3 = timeit.timeit(r"""newline = '\n'
first = 'first'
second = 'second'
f'{first}{newline}{second}'""", number = 10000)
print("That took", t3, end='s to print.\n')
|