небольшая избыточность кода в циклах while (не кажется чистой) - PullRequest
11 голосов
/ 31 мая 2010

Итак, в Python (хотя я думаю, что его можно применять ко многим языкам), я часто сталкиваюсь с чем-то вроде этого:

the_input = raw_input("what to print?\n")
while the_input != "quit":
    print the_input
    the_input = raw_input("what to print?\n")

Может быть, я слишком разборчив, но мне не нравится, как должна повторяться строка the_input = raw_input("what to print?\n"). Это снижает ремонтопригодность и организацию. Но я не вижу обходных путей для избежания дублирования кода без дальнейшего усугубления проблемы. На некоторых языках я мог бы написать что-то вроде этого:

while ((the_input=raw_input("what to print?\n")) != "quit") {
    print the_input
}

Это определенно , а не Pythonic, и Python даже не допускает присваивания в условиях цикла AFAIK.

Этот действительный код исправляет избыточность,

while 1:
    the_input = raw_input("what to print?\n")
    if the_input == "quit":
        break
    print the_input

Но тоже не совсем правильно. while 1 подразумевает, что этот цикл будет работать вечно; Я использую цикл, но задаю ему ложное условие и помещаю в него реальное.

Я слишком придирчив? Есть лучший способ сделать это? Возможно, для этого есть какая-то языковая конструкция, о которой я не знаю?

1 Ответ

30 голосов
/ 31 мая 2010

Подумайте итераторы - например, в данном конкретном случае:

for the_input in iter(lambda: raw_input('what to print?\n'), 'quit'):
    print the_input

Большинство циклов в Python, за исключением самых низких уровней абстракций, лучше всего реализовать как циклы for с помощью некоторого нижележащего итератора, который захватывает «логику циклического преобразования» - встроенная функция iter может помочь (как здесь), иногда можно использовать genexps (выражения генератора), иногда на помощь приходит стандартный библиотечный модуль itertools.

Чаще всего вы выбираете кодирование пользовательских функций генератора (те, которые используют yield), или реже (когда вам нужно действительно сложное управление состоянием) пользовательского класса итератора ( один определяющий специальный метод __iter__ как return self и next [[или __next__ в последних версиях Python]] для возврата «следующего значения из итерации).

Захват логики зацикливания вне зависимости от того, что вы делаете на различных элементах, последовательно создаваемых самим циклом, является ключевым помощником абстракции!

...