Ниже приведен пример класса оболочки вокруг Enum. Я немного странный bu - то, что мне нужно:
public class W2UIEnum<T extends Enum<T> & Resumable> {
public String id;
public String caption;
public W2UIEnum(ApplicationContext appContext, T t) {
this.id = t.getResume();
this.caption = I18N.singleInstance.getI18nString(t.name(), "enum_"
+ t.getClass().getSimpleName().substring(0, 1).toLowerCase()
+ t.getClass().getSimpleName().substring(1,
t.getClass().getSimpleName().length()), appContext
.getLocale());
}
public static <T extends Enum<T> & Resumable> List<W2UIEnum<T>> values(
ApplicationContext appContext, Class<T> enumType) {
List<W2UIEnum<T>> statusList = new ArrayList<W2UIEnum<T>>();
for (T status : enumType.getEnumConstants()) {
statusList.add(new W2UIEnum(appContext, status));
}
return statusList;
}
}
Это странная конструкция даже для опытных программистов Python. При использовании в сочетании с циклами for это в основном означает «найти какой-либо элемент в итерируемом элементе, в противном случае, если ничего не найдено, do ...». Как в:
found_obj = None
for obj in objects:
if obj.key == search_key:
found_obj = obj
break
else:
print('No object found.')
Но всякий раз, когда вы видите эту конструкцию, лучшей альтернативой является либо инкапсуляция поиска в функции:
def find_obj(search_key):
for obj in objects:
if obj.key == search_key:
return obj
, либо использование списка:
matching_objs = [o for o in objects if o.key == search_key]
if matching_objs:
print('Found {}'.format(matching_objs[0]))
else:
print('No object found.')
Он не семантически эквивалентен двум другим версиям, но работает достаточно хорошо в не критичном к производительности коде, где не имеет значения, повторяете ли вы весь список или нет. Другие могут не согласиться, но я бы лично не использовал блоки for-else или while-else в производственном коде.
См. Также [Python-ideas] Краткое содержание for ... else threads
Я рассматриваю структуру как для (если) A else B, так и для (if) -sese является специальным if-else , примерно . Это может помочь понять еще .
A и B выполняются не более одного раза, что аналогично структуре if-else.
for (if) может рассматриваться как специальное условие if, которое выполняет цикл для выполнения условия if. Как только условие , если выполнено, A и нарушают ; Остальное , Б.
Python использует циклы else after for и while, так что если к циклу ничего не применяется, происходит что-то еще. Например:
test = 3
while test == 4:
print("Hello")
else:
print("Hi")
Вывод будет «Привет» снова и снова (если я прав).
• Думайте о else
как о паре с if
внутри цикла (а не с for
) - если условие выполнено, разорвать цикл, иначе сделайте это - за исключением одного else
в паре с несколькими if
с!
• Если if
не было выполнено вообще, то выполните else
.
• Множественные if
с можно также рассматривать как if
- elif
с!
Великолепные ответы:
Моя заметка здесь взята из того, что однажды сказал Дональд Кнут (извините, не могу найти ссылку), что существует конструкция, в которой while-else неотличима от if-else, а именно (в Python):
x = 2
while x > 3:
print("foo")
break
else:
print("boo")
имеет тот же поток (исключая различия низкого уровня) как:
x = 2
if x > 3:
print("foo")
else:
print("boo")
Дело в том, что if-else может рассматриваться как синтаксический сахар для while-else, который имеет неявный break
в конец его if
блока. Противоположный вывод, что цикл while
является расширением до if
, более распространен (это просто повторная / циклическая условная проверка), потому что if
часто преподается раньше while
. Однако это не так, потому что это будет означать, что блок else
в while-else будет выполняться каждый раз , когда условие ложно.
Чтобы облегчить ваше понимание, подумайте об этом так:
Без
break
,return
и т. Д. Цикл заканчивается только тогда, когда условие больше не выполняется, и в таком случаеelse
Блок также будет выполнен один раз. В случае Pythonfor
вы должны рассмотреть циклы в стиле Cfor
(с условиями) или перевести их вwhile
.
Еще одно примечание:
Преждевременное
break
,return
и т. Д. Внутри цикла делает невозможным для условия стать ложным, потому что выполнение выпрыгнуло из цикла, в то время как условие было истинным и он никогда не вернется, чтобы проверить это снова.
for i in range(3):
print(i)
if i == 2:
print("Too big - I'm giving up!")
break;
else:
print("Completed successfully")
«иначе» здесь безумно просто, просто имейте в виду
1, «если for clause
завершено»
for i in range(3):
print(i)
if i == 2:
print("Too big - I'm giving up!")
break;
if "for clause is completed":
print("Completed successfully")
Имеется возможность написать такие длинные операторы как « поскольку предложение завершено ", поэтому они вводят" еще ".
else
здесь, если по своей природе.
2, однако, как насчет for clause is not run at all
In [331]: for i in range(0):
...: print(i)
...:
...: if i == 9:
...: print("Too big - I'm giving up!")
...: break
...: else:
...: print("Completed successfully")
...:
Completed successfully
Так что это полностью утверждение - логическая комбинация:
if "for clause is completed" or "not run at all":
do else stuff
или, если говорить так:
if "for clause is not partially run":
do else stuff
или так:
if "for clause not encounter a break":
do else stuff
Вот еще один идиоматический вариант использования помимо поиска. Допустим, вы хотели подождать, пока условие будет выполнено, например, порт, который будет открыт на удаленном сервере, а также некоторое время ожидания. Тогда вы можете использовать конструкцию while...else
следующим образом:
import socket
import time
sock = socket.socket()
timeout = time.time() + 15
while time.time() < timeout:
if sock.connect_ex(('127.0.0.1', 80)) is 0:
print('Port is open now!')
break
print('Still waiting...')
else:
raise TimeoutError()
Вы можете думать об этом, как, else
как в остальной части материала, или другой материал, который не был сделан в цикле.
Вот способ подумать о том, что я не видел, чтобы кто-то еще упоминал выше:
Во-первых, помните, что for-циклы - это просто синтаксический сахар вокруг while-циклов. Например, цикл
for item in sequence:
do_something(item)
можно переписать (приблизительно) как
item = None
while sequence.hasnext():
item = sequence.next()
do_something(item)
Во-вторых, помните, что циклы while в основном просто повторяются, если-блоки! Вы всегда можете прочитать цикл while как «если это условие истинно, выполнить тело, а затем вернуться и проверить снова».
Так что, хотя / else имеет смысл: это та же структура, что и if / else, с добавленной функциональностью зацикливания до тех пор, пока условие не станет ложным, вместо простой проверки условия один раз.
И тогда for / else также имеет смысл: поскольку все циклы for являются просто синтаксическим сахаром поверх циклов while, вам просто нужно выяснить, каково неявное условное выражение базового цикла while, а затем else соответствует когда это условие становится ложным.
Ключевое слово else
может сбивать с толку, и, как отмечают многие, что-то вроде nobreak
, notbreak
более уместно.
Чтобы логически понять for ... else ...
, сравните его с try...except...else
, а не if...else...
, большинство программистов на python знакомы со следующим кодом:
try:
do_something()
except:
print("Error happened.") # The try block threw an exception
else:
print("Everything is find.") # The try block does things just find.
Аналогично, подумайте о break
] как особый вид Exception
:
for x in iterable:
do_something(x)
except break:
pass # Implied by Python's loop semantics
else:
print('no break encountered') # No break statement was encountered
Разница в python
подразумевает except break
и вы не можете выписать его, поэтому он становится:
for x in iterable:
do_something(x)
else:
print('no break encountered') # No break statement was encountered
Да, я знаю, что это сравнение может быть трудным и утомительным, но оно проясняет путаницу.
Коды в блоке операторов else
будут выполняться, когда цикл for
не был прерван.
for x in xrange(1,5):
if x == 5:
print 'find 5'
break
else:
print 'can not find 5!'
#can not find 5!
Из документов: операторы break и continue, а также предложения о циклах
Операторы цикла могут содержать предложение else; он выполняется, когда цикл завершается из-за исчерпания списка (с помощью for) или когда условие становится ложным (с помощью while), но не тогда, когда цикл завершается оператором break. Это иллюстрируется следующим циклом, который ищет простые числа:
>>> for n in range(2, 10): ... for x in range(2, n): ... if n % x == 0: ... print(n, 'equals', x, '*', n//x) ... break ... else: ... # loop fell through without finding a factor ... print(n, 'is a prime number') ... 2 is a prime number 3 is a prime number 4 equals 2 * 2 5 is a prime number 6 equals 2 * 3 7 is a prime number 8 equals 2 * 4 9 equals 3 * 3
(Да, это правильный код. Посмотрите внимательно: предложение else принадлежит циклу for, а не оператору if.)
При использовании с циклом предложение else имеет больше общего с предложением else оператора try, чем с инструкциями if: предложение else оператора try выполняется, когда не возникает исключение, и else цикла Предложение выполняется, когда не происходит перерыв. Подробнее об операторе try и исключениях см. Обработка исключений.
Оператор continue, также заимствованный из C, продолжает следующую итерацию цикла:
>>> for num in range(2, 10): ... if num % 2 == 0: ... print("Found an even number", num) ... continue ... print("Found a number", num) Found an even number 2 Found a number 3 Found an even number 4 Found a number 5 Found an even number 6 Found a number 7 Found an even number 8 Found a number 9
Я читал это как «Когда iterable
полностью исчерпан, и выполнение собирается перейти к следующему оператору после завершения for
, будет выполнено предложение else». Таким образом, когда итерация нарушена break
, это не будет выполнено.
Так как техническая часть получила довольно много ответов, мой комментарий как раз связан с путаницей , которая приводит к этому переработанному ключевому слову .
Будучи Python очень красноречивым языком программирования, злоупотребление ключевым словом более печально известно. Ключевое слово else
прекрасно описывает часть потока дерева решений: «если вы не можете этого сделать, (иначе) сделайте это». Это подразумевается на нашем родном языке.
Вместо этого использование этого ключевого слова с утверждениями while
и for
создает путаницу. Причина, по которой наша карьера программиста научила нас тому, что утверждение else
находится в дереве решений; его логическая область , обертка, которая условно возвращает путь, по которому нужно следовать. Между тем, циклические операторы имеют явно выраженную цель достичь чего-то. Цель достигается после непрерывных итераций процесса.
if / else
указывают путь для следования . Петли следуют по пути, пока «цель» не будет достигнута .
Проблема в том, что else
- это слово, которое четко определяет последний вариант в условии. Семантика слова этого слова совместно используется Python и Human Language. Но другое слово в человеческом языке никогда не используется для обозначения действий, которые кто-то или что-либо предпримет после того, как что-то будет выполнено. Он будет использоваться, если в процессе его завершения возникнет проблема (более похожая на инструкцию break ).
В конце ключевое слово останется в Python. Понятно, что это была ошибка, понятнее, когда каждый программист пытается придумать историю, чтобы понять ее использование как какое-то мнемоническое устройство. Я бы с удовольствием, если бы они выбрали вместо ключевого слова then
. Я считаю, что это ключевое слово идеально вписывается в этот итеративный поток, выплату после цикла.
Это напоминает ту ситуацию, которая возникает у какого-то ребенка после выполнения каждого шага сборки игрушки: И ТО какой папа?
Я прочитал это примерно так:
Если все еще на условиях для запуска цикла, делать вещи, еще делать что-то еще.
Я думаю, что в документации есть отличное объяснение , иначе , продолжение
[...] выполняется, когда цикл завершается из-за исчерпания список (с помощью for) или когда условие становится ложным (с помощью while), но не тогда, когда цикл завершается оператором break. "
Источник: Документы Python 2: руководство по поток управления
Для простоты вы можете думать об этом так:
for
встречается команда break
, часть else
вызываться не будет. break
в цикле for
, будет вызвана часть else
. Другими словами, если итерация цикла не «нарушена» с break
, будет вызвана часть else
.
Самый простой способ, которым я нашел «получить» то, что сделал for / else, и, что более важно, когда его использовать, это сконцентрироваться на том, куда переходит оператор break. Конструкция For / else представляет собой один блок. Перерыв выпрыгивает из блока и, таким образом, перепрыгивает через условие else. Если бы содержимое предложения else просто следовало за предложением for, оно никогда бы не перепрыгнуло, и поэтому эквивалентную логику нужно было бы предоставить, поместив его в if. Это было сказано ранее, но не совсем в этих словах, так что это может помочь кому-то еще. Попробуйте запустить следующий фрагмент кода. Я искренне поддерживаю комментарий «без перерыва» для ясности.
for a in range(3):
print(a)
if a==4: # change value to force break or not
break
else: #no break +10 for whoever thought of this decoration
print('for completed OK')
print('statement after for loop')
Потому что они не хотели вводить новое ключевое слово в язык. Каждый из них крадет идентификатор и вызывает проблемы обратной совместимости, поэтому обычно это последнее средство.
Существует отличная презентация Раймона Хеттингера под названием Преобразование кода в красивый идиоматический Python , в которой он кратко рассматривает историю конструкции for ... else
. Соответствующий раздел «Различение нескольких точек выхода в петлях» начинается с 15:50 и продолжается около трех минут. Вот основные моменты:
for ... else
была разработана Дональдом Кнутом в качестве замены для некоторых GOTO
вариантов использования; else
имело смысл потому что «это то, что использовал Кнут, и люди знали, что в то время все [for
заявления] включали if
и GOTO
внизу, и они ожидали else
;» Итак, если возникает вопрос: «Почему бы не они меняют это ключевое слово? затем Cat Plus Plus, вероятно, дал самый точный ответ - на данный момент, это будет слишком разрушительным для существующего кода, чтобы быть практичным. Но если вопрос, который вы действительно задаете, заключается в том, почему else
был повторно использован в первую очередь, ну, по-видимому, в то время это казалось хорошей идеей.
Лично мне нравится компромисс комментирования # no break
в строке, где else
можно было бы с первого взгляда ошибочно принять за принадлежность внутри цикла. Это достаточно ясно и кратко. Эта опция получает краткое упоминание в резюме, которое Бьорн связал в конце своего ответа:
Для полноты, я должен упомянуть, что с небольшим изменением синтаксиса программисты, которые хочу, чтобы этот синтаксис мог иметь его прямо сейчас:
for item in sequence: process(item) else: # no break suite
* Бонусная цитата из этой части видео: «Так же, как если бы мы назвали lambda makefunction, никто не спрашивал: «Что делает лямбда?»
Обычная конструкция - запускать цикл до тех пор, пока что-то не будет найдено, а затем вырваться из цикла. Проблема в том, что, если я выйду из цикла или завершу цикл, мне нужно определить, какой случай произошел. Один из способов - создать флаг или переменную хранилища, которая позволит мне выполнить второй тест, чтобы увидеть, как завершился цикл.
Например, предположим, что мне нужно искать в списке и обрабатывать каждый элемент, пока не будет найден элемент флага, а затем прекратить обработку. Если элемент флажка отсутствует, необходимо создать исключение.
Использование Python for
... else
построить у вас есть
for i in mylist:
if i == theflag:
break
process(i)
else:
raise ValueError("List argument missing terminal flag.")
Сравните это с методом, который не использует этот синтаксический сахар:
flagfound = False
for i in mylist:
if i == theflag:
flagfound = True
break
process(i)
if not flagfound:
raise ValueError("List argument missing terminal flag.")
В первом случае raise
тесно связан с циклом for it работает с. Во второй привязка не так сильна, и ошибки могут быть внесены во время обслуживания.
Я согласен, это больше похоже на 'elif not [условие (и), поднимающее разрыв]'.
Я знаю, что это старая ветка, но сейчас я изучаю тот же вопрос, и я не уверен, что кто-нибудь получил ответ на этот вопрос так, как я его понимаю.
Для меня есть три способа «чтения» else
в For... else
или While... else
утверждениях, все из которых эквивалентны:
else
==
if the loop completes normally (without a break or error)
else
==
if the loop does not encounter a break
else
==
else not (condition raising break)
(предположительно, есть такое условие, иначе у вас не будет цикла ) Таким образом, по сути, «else» в цикле на самом деле является «elif ...» где «...» - это (1) без разрыва, что эквивалентно (2) НЕ [условие (и) подъема перерыва].
Я думаю, что ключ в том, что else
бессмысленно без «разрыва», поэтому for...else
включает в себя:
for:
do stuff
conditional break # implied by else
else not break:
do more stuff
Итак, основные элементы цикла for...else
таковы: и вы будете читать их на простом английском языке как:
for:
do stuff
condition:
break
else: # read as "else not break" or "else not condition"
do more stuff
Как говорили другие авторы, обычно возникает разрыв, когда вы можете найти то, что ищет ваша петля, поэтому else:
становится «что делать, если целевой объект не найден».
Пример
Вы также можете использовать обработку исключений, разрывы и циклы для всех вместе.
for x in range(0,3):
print("x: {}".format(x))
if x == 2:
try:
raise AssertionError("ASSERTION ERROR: x is {}".format(x))
except:
print(AssertionError("ASSERTION ERROR: x is {}".format(x)))
break
else:
print("X loop complete without error")
Результат
x: 0
x: 1
x: 2
ASSERTION ERROR: x is 2
----------
# loop not completed (hit break), so else didn't run
Пример
Простой пример с ударом на разрыв.
for y in range(0,3):
print("y: {}".format(y))
if y == 2: # will be executed
print("BREAK: y is {}\n----------".format(y))
break
else: # not executed because break is hit
print("y_loop completed without break----------\n")
Результат
y: 0
y: 1
y: 2
BREAK: y is 2
----------
# loop not completed (hit break), so else didn't run
Пример
Простой пример, где нет перерыва, нет условия, вызывающего перерыв, и нет встречаются ошибки.
for z in range(0,3):
print("z: {}".format(z))
if z == 4: # will not be executed
print("BREAK: z is {}\n".format(y))
break
if z == 4: # will not be executed
raise AssertionError("ASSERTION ERROR: x is {}".format(x))
else:
print("z_loop complete without break or error\n----------\n")
Результат
z: 0
z: 1
z: 2
z_loop complete without break or error
----------