web-dev-qa-db-ja.com

forループの反復回数を変更する

私はこのようなコードを持っています:

loopcount = 3
for i in range(1, loopcount)
   somestring = '7'
   newcount = int(somestring)
   loopcount = newcount

したがって、ループの「内側」のforの範囲を変更する必要があります。

最初のループ中にforループの範囲が(1,7)に変わることを期待してこのコードを書きましたが、実際には起こりませんでした。

代わりに、いくつ入力しても、2回しか実行されません。 (私は6回欲しいです..この場合)

次のようにprintを使用して値を確認しました。

    loopcount = 3
    for i in range(1, loopcount)
       print loopcount
       somestring = '7'
       newcount = int(somestring)
       loopcount = newcount
       print loopcount
#output:
3
7
7
7

なにが問題ですか?番号が変更されました。

私の考えはどこが間違っていますか?

17
H.Choi

範囲は、呼び出されたときのloopcountの値に基づいて作成されます。後でループカウントが発生しても、関係ありません。おそらく必要なのはwhileステートメントです。

loopcount = 3
i = 1
while i < loopcount:
    somestring = '7'
    loopcount = int(somestring)
    i += 1

whileは、条件i < loopcountはtrueであり、trueの場合、含まれているステートメントを実行します。この場合、ループを通過するたびに、iは1ずつ増加します。最初の通過ではloopcountが7に設定されているため、i = 1,2,3,4,5および6の場合、ループは6回実行されます。 。

条件が偽の場合、i = 7、whileループの実行が停止します。

(実際のユースケースが何であるかはわかりませんが、newcountを割り当てる必要がない可能性があるため、削除しました)。

31
Justin Blank

range() docstringから:

range([start、] stop [、step])->整数のリスト

整数の等差数列を含むリストを返します。 range(i、j)は[i、i + 1、i + 2、...、j-1]を返します。 start(!)のデフォルトは0です。stepを指定すると、インクリメント(またはデクリメント)が指定されます。たとえば、range(4)は[0、1、2、3]を返します。終点は省略!これらは、4つの要素のリストに対して正確に有効なインデックスです。

したがって、たとえば、range(1, 10)は次のようなリストを返します:_[1,2,3,4,5,6,7,8,9]_したがって、コードは基本的に次のようになります。

_loopcount = 3
for i in [1, 2]:
    somestring = '7'
    newcount = int(somestring)
    loopcount = newcount
_

forループが「初期化」されると、リストはrange()によって作成されます。

11

user802500によって与えられたwhile-loopの答えは、実際の問題に対する最良の解決策である可能性があります。しかし、私は質問尋ねられたようには興味深くそして有益な答えを持っていると思います。

range()呼び出しの結果は、連続した値のリストです。 forループは、リストがなくなるまでそのリストを繰り返し処理します。

重要なポイントは次のとおりです。反復中にリストを変更できます

>>> loopcount = 3
>>> r = range(1, loopcount)
>>> for i in r:
        somestring = '7'
        newcount = int(somestring)
        del r[newcount:]

この機能の実用的な使用法は、ToDoリスト内のタスクを反復処理し、一部のタスクが新しいToDoを生成できるようにすることです。

for task in tasklist:
    newtask = do(task)
    if newtask:
        tasklist.append(newtask)
3

「範囲の境界を変更するにはどうすればよいですか」という質問に具体的に対処するには、 ジェネレーターのsendメソッド を利用できます。

def adjustable_range(start, stop=None, step=None):
    if stop is None:
        start, stop = 0, start

    if step is None: step = 1

    i = start
    while i < stop:
        change_bound = (yield i)
        if change_bound is None:
            i += step
        else:
            stop = change_bound

使用法:

myrange = adjustable_range(10)

for i in myrange:
    if some_condition:
        myrange.send(20) #generator is now bounded at 20
2
Joel Cornett

range() 関数がfor-ループで評価されると、反復処理に使用される一連の値(つまりリスト)が生成されます。

range()はこれにloopcountの値を使用します。ただし、一度そのシーケンスが生成されると、内部では何もしませんループはそのリストを変更します。つまり、後でloopcountを変更しても、元のリストは同じままです=>反復回数は同じままです。

あなたの場合:

loopcount = 3
for i in range(1, loopcount):

になります

for i in [1, 2]:

したがって、ループ内に2つのprintステートメントがあるため、ループは2回繰り返され、4行の出力が得られます。 loopcountの値を出力していることに注意してください。最初は3ですが、その後7に設定(およびリセット)されます。

反復回数を動的に変更できるようにしたい場合は、代わりにwhileループの使用を検討してください。もちろん、 break ステートメントを使用すると、いつでもループを早期に停止/終了できます。

また、

   somestring = '7'
   newcount = int(somestring)

単純化して

   newcount = 7
2
Levon

あなたの前提は、ループを実行する必要があるデフォルトの回数を持っているが、それが異なるときどきの状態であるということです。代わりにwhileループを使用する方が良いかもしれませんが、次のことを実行できます。

if i == some_calculated_threshold:
    break

代わりにループから抜け出します。

1
moopet

以下は、Joel Cornettが提供するadjustable_range関数のより完全な実装です。

def adjustable_range(start, stop=None, step=None):
    if not isinstance(start, int):
        raise TypeError('start')
    if stop is None:
        start, stop = 0, start
    Elif not isinstance(stop, int):
        raise TypeError('stop')
    direction = stop - start
    positive, negative = direction > 0, direction < 0
    if step is None:
        step = +1 if positive else -1
    else:
        if not isinstance(step, int):
            raise TypeError('step')
        if positive and step < 0 or negative and step > 0:
            raise ValueError('step')
    if direction:
        valid = (lambda a, b: a < b) if positive else (lambda a, b: a > b)
        while valid(start, stop):
            message = yield start
            if message is not None:
                if not isinstance(message, int):
                    raise ValueError('message')
                stop = message
            start += step
0
Noctis Skytower

increase範囲が設定された後の反復回数はできませんが、早期にブレークアウトして反復回数を減らすことができます。

for i in xrange(1, 7):
   if i == 2:
       break
0
kindall