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

Reply via email to