Більш пітонічний спосіб запуску процесу X Times


90

Що є більш пітонічним?

Цикл while:

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

Для циклу:

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

Редагувати: не дублювати, оскільки тут є відповіді, щоб визначити, що зрозуміліше, порівняно з тим, як запустити діапазон без `` i '' - хоча це в кінцевому підсумку було найелегантнішим


8
Голосування для компенсації голосів проти: якщо Лайонел задає це питання, у інших може бути таке саме питання, і відповіді нижче будуть корисними.
Eric O Lebigot

2
Термін "пітонічний" використовується надмірно. Це синонім "читабельного" та "легко зрозумілого". Принаймні в Python.
darioo

Відповіді:


111

Особисто:

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

якщо вам не потрібно i. Якщо ви використовуєте Python <3 і хочете повторити цикл багато разів, використовуйте, xrangeоскільки немає необхідності створювати весь список заздалегідь.


15
Однак слідкуйте за тим, щоб _ не відображався у функції перекладу gettext.
Gintautas Miliauskas

Дякую за цю відповідь; це була основна причина, через яку я не використовував цикл for, оскільки у мене була невикористана змінна в "i".
Лайонел

6
_ подібна до будь-якої іншої змінної. Лише в REPL це має якесь особливе значення. OP також може дотримуватися i.
vezult

2
@vezult Мені це подобається, оскільки це дає зрозуміти, що змінна не використовується в операторі. Чи є, можливо, причина, яка затьмарює це, щоб дотримуватися i?
ryanjdillon

6
Я твердо вірю в додавання поні, особливо коли це звучить доречно ... для поні в діапазоні (50): print ("ржати") # python 3
Paul,

3

Цикл for, безумовно, більш пітонічний, оскільки використовує вбудовану функціональність вищого рівня Python, щоб чіткіше та коротше передати те, що ви робите. Накладні витрати на діапазон проти xrange та присвоєння невикористовуваної iзмінної пов'язані з відсутністю такого оператора, як твердження Verilog repeat. Основна причина дотримуватися рішення щодо діапазону полягає в тому, що інші способи є більш складними. Наприклад:

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 - Zen of Python та PEP 8 - Посібник із стилю для коду Python .

Ми також зауважимо, що версія для діапазону є явним прикладом, що використовується як в мовному довіднику, так і в підручнику , хоча в такому випадку використовується значення. Це означає, що форма обов’язково буде більш звичною, ніж розширення стилю C для циклу.


Чи не було б краще використовувати повторювану річ безпосередньо, тобто: for s in repeat('This is run 10 times', 10): print s??
F1Rumors

Звичайно! Але друк у зразку коду був лише прикладом повторного розділу коду, для якого може не бути центрального об'єкта.
Ян Верньє

Розробник ядра 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 для i в діапазоні (50))
Лука Ране

1
results = itertools.imap (f, range (50))
Лука Ране

@ralu, лише якщо вам не потрібен повторний або випадковий доступ до результатів.
aaronasterling

2
result = кортеж (результати) і набагато швидший за список, оскільки нарізка кортежу дорівнює O (1)
Лука Ране

-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 не є ітерацією.
Ян Верньє

Так, xrange (10) не 10. Я сказав, що це краще, тому що вам не потрібно писати функцію або робити цикл. Однак, як я вже сказав, справжнього пітонічного шляху не існує. Я змінив код, дякую.
Абі М. Сангараб,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.