プロセスをX回実行するためのよりPythonicな方法


90

どちらがよりパイソンですか?

whileループ:

count = 0
while count < 50:
    print "Some thing"
    count = count + 1

Forループ:

for i in range(50):
    print "Some thing"

編集:これはどちらがより明確であるかを決定するための答えを持っているので、重複しないでください、対「i」なしで範囲を実行する方法-それが最もエレガントであることになったとしても


9
反対票を補うための賛成票:ライオネルがこの質問をした場合、他の人も同じ質問をする可能性があり、以下の回答が役立ちます。
Eric O Lebigot 2010年

2
「Pythonic」という用語は多用されています。これは「読みやすい」と「簡単に理解できる」の同義語です。Pythonでは、少なくとも。
darioo 2010年

回答:


115

個人的に:

for _ in range(50):
    print "Some thing"

必要ない場合i。Python <3を使用していて、ループを何度も繰り返したいxrange場合は、事前にリスト全体を生成する必要がないため、を使用してください。


15
ただし、_がgettext変換関数にマップされていることに注意してください。
Gintautas Miliauskas 2010年

この回答をありがとう。これが、「i」に未使用の変数があったためにforループを使用しなかった主な理由でした。
ライオネル

6
_は他の変数とまったく同じです。それが特別な意味を持つのはREPLだけです。OPはに固執することもできiます。
vezult 2012

2
@vezult変数がステートメントで使用されていないことが明確になるので、これが好きです。これに固執するためにこれを覆い隠す理由はおそらくありiますか?
ryanjdillon 2013年

7
私はポニーを追加することを固く信じています。特に適切と思われる場合は... range(50)のポニーの場合:print( "neigh")#python 3
Paul

3

forループは、Pythonの高レベルの組み込み機能を使用して、実行していることをより明確かつ簡潔に伝えるため、間違いなくよりPython的です。rangeとxrangeのオーバーヘッド、および未使用のi変数の割り当ては、Verilogのrepeatステートメントのようなステートメントがないことに起因します。for rangeソリューションに固執する主な理由は、他の方法がより複雑であるということです。例えば:

from itertools import repeat

for unused in repeat(None, 10):
    del unused   # redundant and inefficient, the name is clear enough
    print "This is run 10 times"

ここで範囲の代わりに繰り返しを使用することは、関数としてあまり知られていないためあまり明確ではなく、インポートする必要があるためより複雑です。参照が必要な場合の主なスタイルガイドは、PEP 20-PythonのZenおよびPEP8-Pythonコードのスタイルガイドです

また、for rangeバージョンは、言語リファレンスチュートリアルの両方で使用される明示的な例ですが、その場合は値が使用されます。これは、フォームがCスタイルのforループのwhile拡張よりも馴染みのあるものになるはずであることを意味します。


繰り返されるものを直接使用する方が良いのではないでしょうfor s in repeat('This is run 10 times', 10): print sか。
f1Rumors 2016年

もちろん!ただし、サンプルコードの印刷は、コードの繰り返しセクションの例にすぎず、中心的なオブジェクトがない場合があります。
Yann Vernier 2016年

Pythonのコア開発者は、これが速く使用するよりもあると言うrange() twitter.com/raymondh/status/1144527183341375488
Chris_Rands

int反復ごとに異なるオブジェクトを検索または作成する必要がないため、実際に高速です。ただし、プログラマーの時間は実行時間よりも価値がある場合があります。
ヤン・バーニア

2

ループ内で発生する副作用が必要な場合は、個人的にrange()アプローチを選択します。

ループ内で呼び出す関数の結果が気になる場合は、リスト内包表記またはmapアプローチを使用します。このようなもの:

def f(n):
    return n * n

results = [f(i) for i in range(50)]
# or using map:
results = map(f, range(50))

結果=(f for i in range(50))
Luka Rahne 2010年

1
結果= itertools.imap(f、range(50))
Luka Rahne

@ralu、ただし、結果に繰り返しアクセスしたりランダムにアクセスしたりする必要がない場合のみ。
aaronasterling 2010年

2
result = tuple(results)であり、タプルのスライスはO(1)であるため、リストよりもはるかに高速です
Luka Rahne 2010年

-3

どうですか?

while BoolIter(N, default=True, falseIndex=N-1):
    print 'some thing'

またはもっと醜い方法で:

for _ in BoolIter(N):
    print 'doing somthing'

または、最後にキャッチしたい場合:

for lastIteration in BoolIter(N, default=False, trueIndex=N-1):
    if not lastIteration:
        print 'still going'
    else:
        print 'last time'

どこ:

class BoolIter(object):

    def __init__(self, n, default=False, falseIndex=None, trueIndex=None, falseIndexes=[], trueIndexes=[], emitObject=False):
        self.n = n
        self.i = None
        self._default = default
        self._falseIndexes=set(falseIndexes)
        self._trueIndexes=set(trueIndexes)
        if falseIndex is not None:
            self._falseIndexes.add(falseIndex)
        if trueIndex is not None:
            self._trueIndexes.add(trueIndex)
        self._emitObject = emitObject


    def __iter__(self):
        return self

    def next(self):
        if self.i is None:
            self.i = 0
        else:
            self.i += 1
        if self.i == self.n:
            raise StopIteration
        if self._emitObject:
            return self
        else:
            return self.__nonzero__()

    def __nonzero__(self):
        i = self.i
        if i in self._trueIndexes:
            return True
        if i in self._falseIndexes:
            return False
        return self._default

    def __bool__(self):
        return self.__nonzero__()

-5

何かを繰り返す本当にパイソン的な方法はありません。ただし、それはより良い方法です。

map(lambda index:do_something(), xrange(10))

インデックスを渡す必要がある場合は、次のようにします。

map(lambda index:do_something(index), xrange(10))

結果をコレクションとして返すことを考慮してください。したがって、結果を収集する必要がある場合は、それが役立ちます。


これは実際には良くないだけでなく(関数呼び出しのオーバーヘッド、あまり知られていないラムダ式、未使用の結果をリストに収集する)、10は反復可能ではありません。
Yann Vernier 2014

はい、xrange(10)は10ではありません。関数を記述したりループを作成したりする必要がないので、より良いと言いました。しかし、私が言ったように、本当のpythonicな方法はありません。コードを変更しました、ありがとう。
Abi M.Sangarab 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.