別の方法として、反復/インクリメント操作をラムダ関数に一般化して、次のようなことができるようにしてください。
for i in seq(1, 9, lambda x: x*2):
print i
...
1
2
4
8
は以下seq
のように定義されています。
#!/bin/python
from timeit import timeit
def seq(a, b, f):
x = a;
while x < b:
yield x
x = f(x)
def testSeq():
l = tuple(seq(1, 100000000, lambda x: x*2))
#print l
def testGen():
l = tuple((2**x for x in range(27)))
#print l
testSeq();
testGen();
print "seq", timeit('testSeq()', 'from __main__ import testSeq', number = 1000000)
print "gen", timeit('testGen()', 'from __main__ import testGen', number = 1000000)
パフォーマンスの違いはそれほど大きくありません。
seq 7.98655080795
gen 6.19856786728
[編集]
逆反復をサポートし、デフォルトの引数を使用するには...
def seq(a, b, f = None):
x = a;
if b > a:
if f == None:
f = lambda x: x+1
while x < b:
yield x
x = f(x)
else:
if f == None:
f = lambda x: x-1
while x > b:
yield x
x = f(x)
for i in seq(8, 0, lambda x: x/2):
print i
注: これは、開始値と終了値の違いではなく、方向/テストがイテレータ記号によって選択されるrange
/とは異なる動作をします。xrange
<
>