Więcej Pythonowego sposobu na uruchomienie procesu X razy

90

Co jest bardziej pythonowe?

Pętla While:

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

Dla pętli:

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

Edycja: nie duplikuj, ponieważ zawiera odpowiedzi pozwalające określić, który jest jaśniejszy, w porównaniu z tym, jak uruchomić zakres bez „i” - nawet jeśli okazało się, że jest to najbardziej eleganckie

Lionel
źródło
8
Głosowanie za, aby zrekompensować głosy przeciwne: jeśli Lionel zada to pytanie, inni mogą mieć to samo pytanie, a poniższe odpowiedzi będą przydatne.
Eric O Lebigot
2
Termin „Pythonic” jest nadużywany. To synonim słów „czytelny” i „łatwo zrozumiały”. Przynajmniej w Pythonie.
darioo
Możliwy duplikat Czy można zaimplementować pętlę Python for range bez zmiennej iteratora?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Odpowiedzi:

111

Osobiście:

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

jeśli nie potrzebujesz i. Jeśli używasz Pythona <3 i chcesz powtarzać pętlę wiele razy, użyj, xrangeponieważ nie ma potrzeby wcześniejszego generowania całej listy.

Felix Kling
źródło
15
Uważaj jednak na mapowanie _ do funkcji tłumaczenia gettext.
Gintautas Miliauskas
Dzięki za tę odpowiedź; to był główny powód, dla którego nie korzystałem z pętli for, ponieważ miałem nieużywaną zmienną w „i”.
Lionel
6
_ jest jak każda inna zmienna. Tylko w REPL ma to szczególne znaczenie. OP może równie dobrze się trzymać i.
vezult
2
@vezult Podoba mi się to, ponieważ wyjaśnia, że ​​zmienna nie jest używana w instrukcji. Czy jest może powód, który przesłania to, aby trzymać się i?
ryanjdillon
6
Mocno wierzę w dodawanie kucyków, szczególnie gdy brzmi to odpowiednio ... dla kucyków w zasięgu (50): print ("rżenie") #python 3
Paul
3

Pętla for jest zdecydowanie bardziej pythonowa, ponieważ wykorzystuje wbudowaną funkcjonalność Pythona wyższego poziomu, aby przekazać to, co robisz, zarówno jaśniej, jak i zwięźle. Narzut range vs xrange i przypisywanie nieużywanej izmiennej wynikają z braku instrukcji takiej jak instrukcja Verilog repeat. Głównym powodem, dla którego należy trzymać się rozwiązania for range, jest to, że inne sposoby są bardziej złożone. Na przykład:

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"

Użycie powtórzenia zamiast zakresu jest tutaj mniej jasne, ponieważ nie jest to tak dobrze znana funkcja, a bardziej złożona, ponieważ trzeba ją zaimportować. Jeśli potrzebujesz odniesienia, głównymi przewodnikami stylistycznymi są PEP 20 - The Zen of Python i PEP 8 - Style Guide for Python Code .

Zwracamy również uwagę, że wersja for range jest jawnym przykładem używanym zarówno w odwołaniu do języka, jak iw samouczku , chociaż w tym przypadku używana jest wartość. Oznacza to, że forma jest bardziej znana niż rozwinięcie while pętli for w stylu C.

Yann Vernier
źródło
Czy nie byłoby lepiej użyć bezpośrednio powtórzenia, tj .: for s in repeat('This is run 10 times', 10): print s??
F1Rumors
Na pewno! Ale wydruk w przykładowym kodzie był tylko przykładem powtarzającej się sekcji kodu, dla której może nie być centralnego obiektu.
Yann Vernier
Programista Python twierdzi, że jest to szybsze niż używanie range() twitter.com/raymondh/status/1144527183341375488
Chris_Rands
Jest rzeczywiście szybszy, ponieważ nie musi wyszukiwać ani tworzyć innego intobiektu dla każdej iteracji. Jednak czas programisty może być cenniejszy niż czas wykonania.
Yann Vernier
2

Jeśli szukasz efektów ubocznych, które pojawiają się w pętli, osobiście wybrałbym range()podejście.

Jeśli zależy Ci na wyniku jakichkolwiek funkcji, które wywołujesz w pętli, wybrałbym zrozumienie listy lub mappodejście. Coś takiego:

def f(n):
    return n * n

results = [f(i) for i in range(50)]
# or using map:
results = map(f, range(50))
knutin
źródło
wyniki = (f dla i w zakresie (50))
Luka Rahne
1
results = itertools.imap (f, range (50))
Luka Rahne
@ralu, tylko jeśli nie potrzebujesz wielokrotnego lub losowego dostępu do wyników.
aaronasterling
2
result = tuple (results) i jest znacznie szybszy niż list, ponieważ krojenie krotki to O (1)
Luka Rahne
-3

Co powiesz na?

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

lub w bardziej brzydki sposób:

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

lub jeśli chcesz złapać ostatni raz przez:

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

gdzie:

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__()
DangerMouse
źródło
-5

Nie ma naprawdę pytonicznego sposobu na powtórzenie czegoś. Jest to jednak lepszy sposób:

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

Jeśli chcesz przekazać indeks, to:

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

Weź pod uwagę, że zwraca wyniki jako kolekcję. Jeśli więc chcesz zebrać wyniki, może to pomóc.

Abi M.Sangarab
źródło
Nie tylko nie jest to naprawdę lepsze (obciążenie wywołania funkcji, mniej znane wyrażenia lambda, zbieranie nieużywanych wyników w postaci listy), 10 nie jest iterowalne.
Yann Vernier
Tak, xrange (10) nie 10. Powiedziałem, że jest lepiej, ponieważ nie musisz pisać funkcji ani robić pętli. Jednak, jak powiedziałem, nie ma prawdziwego pytonicznego sposobu. Zmieniłem kod, dzięki.
Abi M.Sangarab