Так, в 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
подразумевает, что этот цикл будет работать навсегда; я использую цикл, но даю ему поддельное условие и помещаю реальное в нем.
Я слишком придирчив? Существует ли лучший способ сделать это? Возможно, существует некоторая конструкция языка, разработанная для этого, что я не знаю о?
Думайте об итераторах - например, в данном конкретном случае:
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]] для возврата "следующего значения из итерации).
Захват логики цикла, помимо того, что вы делаете над различными элементами, последовательно производимыми самим циклом, является здесь ключевой абстракцией-помощником!