web-dev-qa-db-ja.com

Python)でのループ反復のやり直し

Pythonには、一部の言語に存在する「やり直し」ステートメントのようなものがありますか?

(「redo」ステートメントは、(「break」または「continue」のように)ループ動作に影響を与えるステートメントです。最も内側のループの先頭でジャンプし、実行を再開します。)

13

いいえ、そうではありません。 whileループを使用して、チェック変数を初期値にリセットすることをお勧めします。

count = 0
reset = 0
while count < 9:
   print 'The count is:', count
   if not someResetCondition:
       count = count + 1
6
cmaynard

いいえ、Pythonはredoを直接サポートしていません。1つのオプションは、次のようなネストされたループを含むかすかにひどいものです。

for x in mylist:
    while True:
        ...
        if shouldredo:
            continue  # continue becomes equivalent to redo
        ...
        if shouldcontinue:
            break     # break now equivalent to continue on outer "real" loop
        ...
        break  # Terminate inner loop any time we don't redo

ただし、これは、「break-able」ブロック内で、例外に頼ったり、変数にフラグを立てたり、すべてを関数としてパッケージ化したりしない限り、外側のループをredoすることは不可能であることを意味します。

または、whileループが行うことを複製するストレートforループを使用して、イテレータを明示的に作成して進めます。それには独自の問題があります(デフォルトではcontinueは事実上redoであり、「実際の」continueのイテレータを明示的に進める必要があります)が、ひどいわけではありません( continueの使用をコメントして、メンテナの混乱を避けるためにredocontinueの意図を明確にする限り)。 redoおよびその他のループ操作を許可するには、次のようにします。

# Create guaranteed unique sentinel (can't use None since iterator might produce None)
sentinel = object()
iterobj = iter(mylist)  # Explicitly get iterator from iterable (for does this implicitly)
x = next(iterobj, sentinel)  # Get next object or sentinel
while x is not sentinel:     # Keep going until we exhaust iterator
    ...
    if shouldredo:
        continue
    ...
    if shouldcontinue:
        x = next(iterobj, sentinel)  # Explicitly advance loop for continue case
        continue
    ...
    if shouldbreak:
        break
    ...
    # Advance loop
    x = next(iterobj, sentinel)

上記は、2つの引数のtrynextの代わりにsentinel/except StopIteration:を使用して実行することもできますが、ループ全体をラップすると他のソースが危険にさらされますStopIterationがキャッチされ、内部と外部の両方のnext呼び出しに対して限定されたスコープで適切に実行すると、非常に醜くなります(sentinelベースのアプローチよりもはるかに悪い)。

5
ShadowRanger

Perlを勉強しているときに同じ質問に出くわし、このページを見つけました。

perlの本に従ってください:

my @words = qw(fred barney pebbles dino wilma betty);
my $error = 0;

my @words = qw(fred barney pebbles dino wilma betty);
my $error = 0;

foreach (@words){
    print "Type the Word '$_':";
    chomp(my $try = <STDIN>);
    if ($try ne $_){
        print "Sorry - That's not right.\n\n";
        $error++;
        redo;
    }
}

そしてそれをPython ??で達成する方法はコードに従ってください:

tape_list=['a','b','c','d','e']

def check_tape(Origin_tape):
    errors=0
    while True:
        tape=raw_input("input %s:"%Origin_tape)
        if tape == Origin_tape:
            return errors
        else:
            print "your tape %s,you should tape %s"%(tape,Origin_tape)
            errors += 1
            pass

all_error=0
for char in tape_list:
    all_error += check_tape(char)
print "you input wrong time is:%s"%all_error

Pythonには「やり直し」構文はありませんが、リストを反復処理するときに必要なものが得られるまで、一部の関数で「while」ループを作成できます。

2
xianbo yang

これは、イテレータを使用した私のソリューションです。

_class redo_iter(object):
    def __init__(self, iterable):
        self.__iterator = iter(iterable)
        self.__started = False
        self.__redo = False
        self.__last = None
        self.__redone = 0
    def __iter__(self):
        return self
    def redo(self):
        self.__redo = True
    @property
    def redone(self):
        return self.__redone
    def __next__(self):
        if not (self.__started and self.__redo):
            self.__started = True
            self.__redone = 0
            self.__last = next(self.__iterator)
        else:
            self.__redone += 1
        self.__redo = False
        return self.__last


# Display numbers 0-9.
# Display 0,3,6,9 doubled.
# After a series of equal numbers print --
iterator = redo_iter(range(10))
for i in iterator:
    print(i)
    if not iterator.redone and i % 3 == 0:
        iterator.redo()
        continue
    print('---')
_
  • 明示的なcontinueが必要
  • redoneは追加機能です
  • Python2の場合、def next(self)の代わりにdef __next__(self)を使用します
  • ループの前にiteratorを定義する必要があります
0
Piotr Ćwiek

あまり洗練されていませんが、ループの最後にwhileとインクリメントを使用して、読みやすくなっています。したがって、間にあるcontinueは、やり直しの効果があります。 3の倍数ごとにやり直すサンプル。

redo = True # To ends redo condition in this sample only
i = 0
while i<10:
   print(i, end='')
   if redo and i % 3 == 0:
      redo = False # To not loop indifinively in this sample
      continue # Redo
   redo = True
   i += 1

結果:00123345667899

0
Le Droid