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.
_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe:
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com