-
-
Notifications
You must be signed in to change notification settings - Fork 30.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Accelerate 'string' % (value, ...) by using formatted string literals #72494
Comments
For now using formatted string literals (PEP-498) is the fastest way of formatting strings. $ ./python -m perf timeit -s 'k = "foo"; v = "bar"' -- '"%s = %r" % (k, v)'
Median +- std dev: 2.27 us +- 0.20 us
$ ./python -m perf timeit -s 'k = "foo"; v = "bar"' -- 'f"{k!s} = {v!r}"'
Median +- std dev: 1.09 us +- 0.08 us The compiler could translate C-style formatting with literal format string to the equivalent formatted string literal. The code '%s = %r' % (k, v) could be translated to t1 = k; t2 = v; f'{t1!r} = {t2!s}'; del t1, t2 or even simpler if k and v are initialized local variables. $ ./python -m perf timeit -s 'k = "foo"; v = "bar"' -- 't1 = k; t2 = v; f"{t1!s} = {t2!r}"; del t1, t2'
Median +- std dev: 1.22 us +- 0.05 us This is not easy issue and needs first implementing the AST optimizer. |
There isn't a direct mapping between %-formatting and __format__ format specifiers. Off the top of my head, I can think of at least one difference: >>> '%i' % 3
'3'
>>> '{:i}'.format(3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Unknown format code 'i' for object of type 'int' So you'll need to be careful with edge cases like this. Also, for all usages of %s, remember to call str() (or add !s): >>> '%s' % 1
'1'
>>> f'{1:s}'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Unknown format code 's' for object of type 'int'
>>> f'{1!s:s}'
'1'
Although that also reminds me of this default alignment difference:
>>> x=0
>>> '%2s' % x
' 0'
>>> f'{x!s:2s}'
'0 '
>>> f'{x!s:>2s}'
' 0' So, in general, the mapping will be difficult. On the other hand, if you can do it, and provide a function that maps between %-formatting codes and __format__ codes, then that might be a generally useful tool. |
'%s' % x should be translated to f'{x!s}', not to f'{x:s}'. Only %s, %r and %a can be supported. Formatting with %i should left untranslated. Or maybe translate '%r: %i' % (a, x) to f'{a!r}: {"%i" % x}'. It is possible also to introduce special opcodes that converts argument to exact int or float. Then '%06i' % x could be translated to f'{exact_int(x):06}'. |
Serhiy, you actually did make a mistake above; (just try with |
Thanks for the correction Antti. Yes, this is what I initially meant. This optimization is applicable only if the left argument of % is a literal string and the right argument is a tuple expression. Saying about |
PR 5012 implements transformation simple format strings containing only %s, %r and %a into f-strings. |
I'm +1 on this optimization. |
PR 26160 adds support of %d, %i, %u, %o, %x, %X, %f, %e, %g, %F, %E, %G. What is not supported:
|
commit a0bd9e9
commit 8b01067
|
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: