8

私は最近 Python の学習を始めましたが、for ループの概念はまだ少し混乱しています。for x in y一般に、yは単なるリストの形式に従うことを理解しています。

for-each ループfor (int n: someArray)for n in someArray

for ループは次のfor (i = 0; i < 9; i-=2)ように表すことができます。for i in range(0, 9, -2)

一定の増分の代わりに、i*=2、またはが欲しかったとしi*=iます。これは可能ですか、代わりに while ループを使用する必要がありますか?

4

5 に答える 5

12

あなたが言うように、forループはリストの要素を繰り返します。リストには好きなものを含めることができるため、各ステップを含むリストを事前に作成できます。

forループは、実際のリストではなく小さなコードである"generator"を反復処理することもできます。Python では、range()実際にはジェネレーターです (ただし、Python 2.x では、ジェネレーターであるときにrange()リストを返しましたxrange())。

例えば:

def doubler(x):
    while True:
        yield x
        x *= 2

for i in doubler(1):
    print i

上記のforループは印刷されます

1
2
4
8

Ctrl+C を押すまで続きます。

于 2012-05-03T23:08:13.237 に答える
8

ジェネレーター式を使用して、これを効率的に、余分なコードをほとんど使用せずに行うことができます。

for i in (2**x for x in range(10)): #In Python 2.x, use `xrange()`.
    ...

ジェネレーター式は、リスト内包表記に似た構文を使用して、 ( Greg Hewgill の回答のように) 手動ジェネレーターを定義するのと同じように機能します。それらは遅延評価されます。つまり、操作の開始時にリストを生成しないため、大きな iterable でパフォーマンスが大幅に向上します。

したがって、このジェネレーターは、値を要求されるまで待ってから、値を要求range(10)し、その値を 2 倍にして、forループに戻します。range()ジェネレーターが値を生成しなくなるまで、これを繰り返します。

于 2012-05-03T23:15:18.763 に答える
5

Pythonの「リスト」部分は任意の反復可能なシーケンスである可能性があることに注意してください。

例:

文字列:

for c in 'abcdefg':
   # deal with the string on a character by character basis...

ファイル:

with open('somefile','r') as f:
    for line in f:
         # deal with the file line by line

辞書:

d={1:'one',2:'two',3:'three'}
for key, value in d.items():
   # deal with the key:value pairs from a dict

リストのスライス:

l=range(100)
for e in l[10:20:2]:
    # ever other element between 10 and 20 in l 

などなどなど

だから、それは本当に「ほんの一部のリスト」よりもはるかに深いです

他の人が述べているように、iterableを、例の質問に対して希望するものに設定するだけです。

 for e in (i*i for i in range(10)):
     # the squares of the sequence 0-9...

 l=[1,5,10,15]
 for i in (i*2 for i in l):
     # the list l as a sequence * 2...
于 2012-05-03T23:19:47.963 に答える
1

これにはリスト内包表記を使用する必要があります

print [x**2 for x in xrange(10)] # X to the 2nd power.

print [x**x for x in xrange(10)] # X to the Xth power.

リスト内包表記の構文は次のとおりです。

[EXPRESSION for VARIABLE in ITERABLE if CONDITION]

内部的には、 map および filter 関数と同様に機能します。

def f(VARIABLE): return EXPRESSION
def c(VARIABLE): return CONDITION

filter(c, map(f, ITERABLE))

与えられた例:

def square(x): return x**2

print map(square, xrange(10))

def hypercube(x): return x**x

print map(hypercube, xrange(10))

リスト内包表記が気に入らない場合は、代替アプローチとして使用できます。forループを使用することもできますが、それはPythonの慣用句から離れます...

于 2012-05-03T23:08:03.820 に答える
0

別の方法として、反復/インクリメント操作をラムダ関数に一般化して、次のようなことができるようにしてください。

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<>

于 2013-11-25T10:01:25.280 に答える