[Python-Dev] Examples for PEP 572 (original) (raw)
Serhiy Storchaka storchaka at gmail.com
Wed Jul 4 03:51:50 EDT 2018
- Previous message (by thread): [Python-Dev] Examples for PEP 572
- Next message (by thread): [Python-Dev] Examples for PEP 572
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
04.07.18 04:54, Terry Reedy пише:
Would (f(x),) be faster?
No. Both "for y in [f(x)]" and "for y in (f(x),)" are compiled to the same bytecode. Run your microbenchmarks again, the difference is a small random variation.
https://bugs.python.org/issue32925
stuff = [[y := f(x), x/y] for x in range(5)] stuff = [[y, x/y] for x in range(5) for y in [f(x)]] Creating an leaky name binding appears to about 5 x faster than iterating a temporary singleton.
With issue32856 be merged, "for var in [expr]" will be compiled to the same bytecode as just "var = expr". This is a simple optimization, and this is a good kind of changes that increase performance for free, without needing users to use a new syntax. It is not merged yet because I have doubts that the need in the assignment inside comprehensions is worth even such small complication of the compiler (of course PEP 572 adds much more complications, and not only to the code generator).
If you need to write the above artificial example as a comprehension, lets just merge issue32856.
https://bugs.python.org/issue32856
The 2-argument form of iter is under-remembered and under-used. The length difference is 8. while (command := input("> ")) != "quit": for command in iter(lambda: input("> "), "quit"):
This doesn't look like a good rationale for such large change as PEP 572.
I like the iter version, but the for-loop machinery and extra function call makes a minimal loop half a millisecond slower.
import timeit as ti def s(): it = iter(10000*'0' + '1') def w(): it = iter(10000*'0' + '1') while True: command = next(it) if command == '1': break def f(): it = iter(10000*'0' + '1') for command in iter(lambda: next(it), '1'): pass print(ti.timeit('s()', 'from main import s', number=1000)) print(ti.timeit('w()', 'from main import w', number=1000)) print(ti.timeit('f()', 'from main import f', number=1000)) # 0.0009702129999999975 0.9365254250000001 1.5913117949999998
Using partial() makes it faster:
from functools import partial def p(): it = iter(10000*'0' + '1') for command in iter(partial(next, it), '1'): pass
print(ti.timeit('s()', 'from main import s', number=1000)) print(ti.timeit('w()', 'from main import w', number=1000)) print(ti.timeit('f()', 'from main import f', number=1000)) print(ti.timeit('p()', 'from main import p', number=1000)) # 0.0016302559961332008 0.7507075049943523 1.3297416319983313 0.6211225209990516
Of course, with added processing of 'command' the time difference disappears.
Yes, and this is why I didn't bother about a tiny overhead of a lambda. You can use partial() in a tight performance critical loop. It is even faster than a bare while loop.
# Capturing regular expression match objects # See, for instance, Lib/pydoc.py, which uses a multiline spelling # of this effect if match := re.search(pat, text): print("Found:", match.group(0)) # The same syntax chains nicely into 'elif' statements, unlike the # equivalent using assignment statements. elif match := re.search(otherpat, text): print("Alternate found:", match.group(0)) elif match := re.search(third, text): print("Fallback found:", match.group(0)) It may be more efficient to use a single regular expression which consists of multiple or-ed patterns My attempt resulted in a slowdown. Duplicating the dominance of pat over otherpat over third requires, I believe, negative lookahead assertions.
I have to admit that this example will not get a benefit from rewriting with a single regular expression. I was fooled by the misleading reference to pydoc.py. The code in pydoc.py doesn't have anything common with this example, it searches the first occurrence of the set of patterns in a loop, while the example searches patterns sequentially and only once. The code similar to pydoc.py is common, but I would want to see a real code that corresponds the example in PEP 572.
- Previous message (by thread): [Python-Dev] Examples for PEP 572
- Next message (by thread): [Python-Dev] Examples for PEP 572
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]