Comments 63
Спасибо. Продолжайте — у вас хорошо получается.
Красиво и доступно. Спасибо.
Большое спасибо Вам, а также всем тем кто поддерживает эту тему. Задумался над тем, чтоды добавить изучение Питона для школьников в кружке. Как один из 2-х языков. Первый разумеется Паскаль.
> Существует так же краткая форма записи (аналог тернарного оператора в Си): X = A if условие else B
Можно еще упомянуть про логические операторы or и and, которые так же можно использовать для данной конструкции:
Отсюда можно выводить и следующие производные:
Все дело в особенности операторов or и and:
— or возвращает левый операнд, если он истинен, иначе — правый;
— and — вернет результат самого правого операнда, если все предыдущие были истины.
Когда условия одиночны, то такая запись может быть очень удобной (не нужно городить лишние if-else-блоки), если же условий несколько, то лучше воспользоваться if-else'ами, чтобы не портить читаемость кода.
P.S.> в JavaScript и Ruby аналогичная функциональность этих операндов.
Можно еще упомянуть про логические операторы or и and, которые так же можно использовать для данной конструкции:
x = условие and a or b
Отсюда можно выводить и следующие производные:
b = a or 10 # либо «а», либо дефолтное значение
# можно, например, и функцию вызвать по условию:
def c(): print('O.k')
b and c() # функция «с» вызовется только в том случае, если b — истинно
Все дело в особенности операторов or и and:
— or возвращает левый операнд, если он истинен, иначе — правый;
— and — вернет результат самого правого операнда, если все предыдущие были истины.
Когда условия одиночны, то такая запись может быть очень удобной (не нужно городить лишние if-else-блоки), если же условий несколько, то лучше воспользоваться if-else'ами, чтобы не портить читаемость кода.
P.S.> в JavaScript и Ruby аналогичная функциональность этих операндов.
Да, совершенно верно; уже ниже упомянул — habrahabr.ru/blogs/starting_programming/50120/#comment_1316458
if условие1:
блок1
elif условие2:
блок2
else:
блок3
elif или elseif?
блок1
elif условие2:
блок2
else:
блок3
elif или elseif?
большое спасибо… учу с вами питон… продолжайте
товарищ cleg — найдите пожалуйста время и продолжайте уроки, лично я очень жду ;)
товарищ cleg — найдите пожалуйста время и продолжайте уроки, лично я очень жду ;)
скобки лишние
>>> for (x,y) in L:
>>> for (x,y) in L:
Ненужное дублирование:
for elem in list1:
print (elem,'found') if elem in list2 else (elem,'not found')
--->
print (elem,'found' if elem in list2 else 'not found')
for elem in list1:
print (elem,'found') if elem in list2 else (elem,'not found')
--->
print (elem,'found' if elem in list2 else 'not found')
Объясните смысл
Разве это:
не равнозначно записи
else
и finally
в try
.Разве это:
try:
..block 1
else:
..block 2
finally:
..block 3
не равнозначно записи
try:
..block 1
..block 2
block 3
У меня поверхностное знакомство с питоном, но могу рискнуть:
В первом случае при возникновении исключения в «block 1», он на самом деле не будет выполнен, т.к. там есть ошибка вызывающая эксепшн, управление перейдёт на «block 2», который выполнится. Затем выполнится «block 3».
Во втором случае, при возникновении эксепшна в «block 1», управление перейдёт сразу на «block 3» минуя «block 2».
В первом случае при возникновении исключения в «block 1», он на самом деле не будет выполнен, т.к. там есть ошибка вызывающая эксепшн, управление перейдёт на «block 2», который выполнится. Затем выполнится «block 3».
Во втором случае, при возникновении эксепшна в «block 1», управление перейдёт сразу на «block 3» минуя «block 2».
Не просто не имеет, но и грамматика это явно запрещает.
try: print "TRY!" finally: print "Finally!" === TRY! Finally!
Замечательно работает. Остальное же — да, запрещено, да и смысла, вроде, не имеет. Зачем может понадобиться try/else сочетание — ума не приложу %)
А это уже отдельный вопрос :) Я всё жду, когда начнётся обсуждение исключений, чтобы там позадавать вопросы относительно соответствия реализации языка его формальной грамматике. Грамматика явно требует наличия как минимум одного блока except.
Насчёт try и else
То есть смысл в том, чтобы отловить любое исключение, которое вылезет (считаем, что самого базового класса нет). В такой интерпретации я не вижу особого смысла в блоке finally.
Насчёт try и else
try: do_something except E1: # ловим исключение 1 except E2: # ловим исключение 2 else: # ловим все остальные исключения finally: # делаем что-то там в случае чего-то там
То есть смысл в том, чтобы отловить любое исключение, которое вылезет (считаем, что самого базового класса нет). В такой интерпретации я не вижу особого смысла в блоке finally.
> else: # ловим все остальные исключения
> То есть смысл в том, чтобы отловить любое исключение, которое вылезет (считаем, что самого базового класса нет)
Ветвь else выполнится только в том случае, если блок try не сгенерировал исключение. Рациональное объяснение: лучше дополнительный код, который должен быть выполнен при успешном try'e помещать в else, это позволит избежать обработку исключений, сгенерированных кодом, который мы не собирались защищать.
> То есть смысл в том, чтобы отловить любое исключение, которое вылезет (считаем, что самого базового класса нет)
Ветвь else выполнится только в том случае, если блок try не сгенерировал исключение. Рациональное объяснение: лучше дополнительный код, который должен быть выполнен при успешном try'e помещать в else, это позволит избежать обработку исключений, сгенерированных кодом, который мы не собирались защищать.
Приношу извенения, ошибся. Случай try:… finally в грамматике отдельно рассматривается.
Не так важно, я упростил.
Разве это:
try:
..block 1
except:
..show msg
else:
..block 2
finally:
..block 3
не равнозначно записи
try:
..block 1
..block 2
block 3
Разве это:
try:
..block 1
except:
..show msg
else:
..block 2
finally:
..block 3
не равнозначно записи
try:
..block 1
..block 2
block 3
Не так важно, я упростил.
Разве это:
try:
..block 1
except:
..show msg
else:
..block 2
finally:
..block 3
не равнозначно записи
try:
..block 1
..block 2
block 3
Разве это:
try:
..block 1
except:
..show msg
else:
..block 2
finally:
..block 3
не равнозначно записи
try:
..block 1
..block 2
block 3
Разве это:
try:
..block 1
except:
..show msg
else:
..block 2
finally:
..block 3
не равнозначно записи
try:
..block 1
..block 2
except:
..show msg
block 3
За исключением разве обработки исключения в блоке 2.
Я не вижу разницы.
try:
..block 1
except:
..show msg
else:
..block 2
finally:
..block 3
не равнозначно записи
try:
..block 1
..block 2
except:
..show msg
block 3
За исключением разве обработки исключения в блоке 2.
Я не вижу разницы.
И если уж обработка исключения в блоке 2 принципиальна, разницы в finally нету совсем:
try:
..block A
except:
..show msg
finally:
..block B
эквивалентно
try:
..block A
except:
..show msg
block B
try:
..block A
except:
..show msg
finally:
..block B
эквивалентно
try:
..block A
except:
..show msg
block B
Позволю себе не согласиться ;)
finally мне видится полезным при работе с ресурсами, которые обязательно надо освободить. В случае же exception-а ресурс может оказаться занятым. Например, открытый файл, сокет, всякие семафоры с флагами и т.п.
Мне сейчас скажут, что есть же with, но он далеко не всегда доступен :( Говорят, в python 3000 with должен поддерживаться большей частью библиотек, для версий же 2.5-2.6 это не так. Сам, недавно испольpуя urllib, с огорчением для себя обнаружил, что с ним with не работает.
finally мне видится полезным при работе с ресурсами, которые обязательно надо освободить. В случае же exception-а ресурс может оказаться занятым. Например, открытый файл, сокет, всякие семафоры с флагами и т.п.
Мне сейчас скажут, что есть же with, но он далеко не всегда доступен :( Говорят, в python 3000 with должен поддерживаться большей частью библиотек, для версий же 2.5-2.6 это не так. Сам, недавно испольpуя urllib, с огорчением для себя обнаружил, что с ним with не работает.
в принципе — логика простая.
в блоке
блок else выполняется только в том случае если в блоке try не было исключительной ситуации.
а finally — выполнится всегда гарантированно, даже если в блоке try был вызван выход из функции (например)
попробуйте раскомментировать строчку с делением на ноль, и т.п.
в блоке
try:
# blah balh blah
except Error as err:
# poom poom poom
else:
# dah dah dah
finally:
# zoom zoom zoom
блок else выполняется только в том случае если в блоке try не было исключительной ситуации.
а finally — выполнится всегда гарантированно, даже если в блоке try был вызван выход из функции (например)
def func1():
try:
# print 1/0
pass
return
except Exception as ex:
print repr(ex)
else:
print "else"
finally:
print "finally"
func1()
попробуйте раскомментировать строчку с делением на ноль, и т.п.
в принципе водогнку…
для try… except… else… finally… usecase весьма прост:
для try… except… else… finally… usecase весьма прост:
try:
# делаем что-то критичное
# можем даже вызвать если надо return
# обычно - открываем файл, коннектимся к бд и т.п.
except Error as err:
# ой, словили эксепшн - сообщаем пользователю и т.п.
else:
# все хорошо, работаем с ресурсом
finally:
# убираем за собой, и не важно что случится - мы всегда уберем
</code>
Это понятно.
Но ваш код и мой код напишут то же самое:
Но ваш код и мой код напишут то же самое:
МЛЯТЬ, почему он отправляется сам??
habrahabr.ru/blogs/starting_programming/50120/#comment_1315751
Блок else идеологически выделен, чтобы вынести в него код, который должен быть выполнен в случае успеха (в случае, если в try не произойдут исключений). Теоретически и практически, весь код блока else можно и записать в сам try, однако, в try желательно писать только то, что должно быть защищено. Остальной успешный код лучше вынести в else, поскольку в самом этом коде могут быть также исключения и, если они будут в try'e, то будут обрабатываться нашими except'aми, которые предназначены для обработки для конкретных типов исключений.
Блок else идеологически выделен, чтобы вынести в него код, который должен быть выполнен в случае успеха (в случае, если в try не произойдут исключений). Теоретически и практически, весь код блока else можно и записать в сам try, однако, в try желательно писать только то, что должно быть защищено. Остальной успешный код лучше вынести в else, поскольку в самом этом коде могут быть также исключения и, если они будут в try'e, то будут обрабатываться нашими except'aми, которые предназначены для обработки для конкретных типов исключений.
Спасибо, это весьма доходчиво!
Все равно не понятно ЗАЧЕМ это нужно.
Если мы не предусмотрели except для исключения из «успешного» кода, он не будет обработан.
Может кто-нибудь пример из рабочего кода приведет, где это действительно надо делать через else?
Если мы не предусмотрели except для исключения из «успешного» кода, он не будет обработан.
Может кто-нибудь пример из рабочего кода приведет, где это действительно надо делать через else?
> Все равно не понятно ЗАЧЕМ это нужно.
В данном случае, программа упадет на else (поскольку будет деление на 0).
Если в try'e использовать только вторую строку (b = a['c']), то поймается KeyError и else не будет обработан.
Если в try'e использовать строки 1 и 3 (b = a['x'] и print(1 / b)), то поймается общий Exception, но! — не для того случая, который мы защищали (b = a['несуществующий_ключ']), а для «непредвиденного» — из «успешного» кода (в данном случае — тривиальный — деление на ноль, где ноль — предварительно полученный код из защищаемого кода). В данном случае, наш Exception поймал исключение, но предназначался этот Exception не для этого исключения. Т.е. мы будем считать, что мы что-то обработали, на самом же деле — код должен упасть в else, сигнализируя, что помимо кода, который мы защитили, есть еще один такой код и его так же надо обрабатывать, но, возможно, совершенно другими классами исключений (это основная суть).
Так что здесь вопрос, скорее, идеологический (ничто не мешает использовать этот «успешный» код и в самом try'e и вообще — за пределами try-блока), просто ввели такой синтаксический сахар в виде else.
P.S> в Ruby этот else-блок тоже присуствует в данном блоке.
a = {'x': 0} try: b = a['x'] #b = a['c'] #print(1 / b) except KeyError as e: print('KeyError') except Exception as e: print('Common Exception') else: print(1 / b) finally: print('finally')
В данном случае, программа упадет на else (поскольку будет деление на 0).
Если в try'e использовать только вторую строку (b = a['c']), то поймается KeyError и else не будет обработан.
Если в try'e использовать строки 1 и 3 (b = a['x'] и print(1 / b)), то поймается общий Exception, но! — не для того случая, который мы защищали (b = a['несуществующий_ключ']), а для «непредвиденного» — из «успешного» кода (в данном случае — тривиальный — деление на ноль, где ноль — предварительно полученный код из защищаемого кода). В данном случае, наш Exception поймал исключение, но предназначался этот Exception не для этого исключения. Т.е. мы будем считать, что мы что-то обработали, на самом же деле — код должен упасть в else, сигнализируя, что помимо кода, который мы защитили, есть еще один такой код и его так же надо обрабатывать, но, возможно, совершенно другими классами исключений (это основная суть).
Так что здесь вопрос, скорее, идеологический (ничто не мешает использовать этот «успешный» код и в самом try'e и вообще — за пределами try-блока), просто ввели такой синтаксический сахар в виде else.
P.S> в Ruby этот else-блок тоже присуствует в данном блоке.
То есть мы просто не хотим ловить деление на 0 в данном месте?
Тогда зачем нам ловить общий Exception?
Ну в общем ясно: хотите — используйте else, хотите — без него.
А если в else будет эксепшн, finally отработает?
Тогда зачем нам ловить общий Exception?
Ну в общем ясно: хотите — используйте else, хотите — без него.
А если в else будет эксепшн, finally отработает?
> То есть мы просто не хотим ловить деление на 0 в данном месте?
Не ловить в смысле в общих except'ax или сделать еще внутренний try-except в основмном try'e? Первый случай, как раз-таки нежелателен — получается мы общими except'ами пытаемся отловить все, соответственно, и в try'e у нас каша — сколько случаев мы в нем пытаемся защитить?
Если будет внутренний try-except во внешнем try — да, так, конечно, можно, тогда не должно быть внешнего else-блока (поскольку он тоже выполнится, т.к. во внешнем try'e все пройдет успешно).
Однако, если вынести успешный код в else и сделать там try-except — мы разграничиваем типы исключений.
В общем, повторю, это лишь удобный синтаксический сахар (ничто не запрещает написать этот успешный код со своими try-except'aми и после основного try'я)
> А если в else будет эксепшн, finally отработает?
Да.
Не ловить в смысле в общих except'ax или сделать еще внутренний try-except в основмном try'e? Первый случай, как раз-таки нежелателен — получается мы общими except'ами пытаемся отловить все, соответственно, и в try'e у нас каша — сколько случаев мы в нем пытаемся защитить?
Если будет внутренний try-except во внешнем try — да, так, конечно, можно, тогда не должно быть внешнего else-блока (поскольку он тоже выполнится, т.к. во внешнем try'e все пройдет успешно).
Однако, если вынести успешный код в else и сделать там try-except — мы разграничиваем типы исключений.
В общем, повторю, это лишь удобный синтаксический сахар (ничто не запрещает написать этот успешный код со своими try-except'aми и после основного try'я)
> А если в else будет эксепшн, finally отработает?
Да.
Нет, подождите. Опять все запутывается. =)
Мы хотим поймать деление на 0 в этом блоке кода?
Если да — то вместо «except Exception as e:» пишем «except ZeroDivisionError as e:».
Если нет — то вместо «except Exception as e:» вообще ничего не пишем.
И не надо никаких вложенных try..except и естественно else.
Единственно возможным вариантом (и то с натяжкой) использования else я вижу ситуацию, когда у нас есть внутри try 2 куска кода, которые могут выбросить одинаковый эксепшн, но первый мы хотим ловить, а второй нет. Или второй мы хотим обработать по другому, и тогда внутри else еще один try..except. Хотя его с тем же успехом можно всунуть внутрь первого try.
Мы хотим поймать деление на 0 в этом блоке кода?
Если да — то вместо «except Exception as e:» пишем «except ZeroDivisionError as e:».
Если нет — то вместо «except Exception as e:» вообще ничего не пишем.
И не надо никаких вложенных try..except и естественно else.
Единственно возможным вариантом (и то с натяжкой) использования else я вижу ситуацию, когда у нас есть внутри try 2 куска кода, которые могут выбросить одинаковый эксепшн, но первый мы хотим ловить, а второй нет. Или второй мы хотим обработать по другому, и тогда внутри else еще один try..except. Хотя его с тем же успехом можно всунуть внутрь первого try.
Я бы заменил фразу «# выполнится, если выход из цикла не осуществлялся инструкцией break» на «# выполняется, если выход из цикла был произведён не инструкцией break» для единообразия.
да, статья про расширенное использование функций — будет… надеюсь завтра.
Классная статья, отдельное спасибо за пример.
Хочу добавить пару слов о конструкциях вида: X = A if S else B. Есть еще более экзотичные способы, например:
X = [B, A][bool(S)]
или
X = ( (A and S) or B )
Все 3 примера сработают одинаково.
Хочу добавить пару слов о конструкциях вида: X = A if S else B. Есть еще более экзотичные способы, например:
X = [B, A][bool(S)]
или
X = ( (A and S) or B )
Все 3 примера сработают одинаково.
Не совсем так. Третий пример не эквивалентен первому. Например, когда S имеет ложное значение.
Пример:
Второй пример будет работать медленнее, чем первый. Т.к. в первом используется сокращённая схема вычислений, а во втором полная.
Короче говоря, иметь представление об альтернативных вариантах — полезно. Т.к. они могут встретиться в старом коде (когда тернарный оператор ещё не был введён). Но в новом коде следует использовать только первый вариант. Читаемость кода — это тоже немаловажный фактор, согласитесь ;)
Пример:
>>> A = 0
>>> S = 1
>>> B = 'hi'
>>> A if S else B
0
>>> ((A and S) or B)
'hi'
Второй пример будет работать медленнее, чем первый. Т.к. в первом используется сокращённая схема вычислений, а во втором полная.
Короче говоря, иметь представление об альтернативных вариантах — полезно. Т.к. они могут встретиться в старом коде (когда тернарный оператор ещё не был введён). Но в новом коде следует использовать только первый вариант. Читаемость кода — это тоже немаловажный фактор, согласитесь ;)
> ((A and S) or B)
только наоборот — S and A or B (если сравнивать с A if S else B), но сути это не меняет:
поскольку, действительно, эти два варианта работают по-разному: второй вариант трактует полученный ноль (S and A) как ложь и, соответственно, переходит к вычислению в B. Поэтому, если нужно учитывать 0, второй вариант уже не подходит. Поэтому, да — для общего случая лучше использовать вариант с A if S else B.
Для одиночных же проверок (a and b, c = x || 'defaultValue'), будут работать нормально.
только наоборот — S and A or B (если сравнивать с A if S else B), но сути это не меняет:
поскольку, действительно, эти два варианта работают по-разному: второй вариант трактует полученный ноль (S and A) как ложь и, соответственно, переходит к вычислению в B. Поэтому, если нужно учитывать 0, второй вариант уже не подходит. Поэтому, да — для общего случая лучше использовать вариант с A if S else B.
Для одиночных же проверок (a and b, c = x || 'defaultValue'), будут работать нормально.
Условная инструкция if Думаю тут всё понятно: if условие1: блок1 elif условие2: блок2 else: блок3
Может я где-то что-то упустил, но не могу ни в одной «унции» найти а как, собственно, задается блок, если там больше одного выражения? В примерах не вижу ни привычных {...}, ни какого-нибудь end (хоть c begin как в паскале, хоть без, как в альтернативном синтаксисе PHP)… Глазами смотришь — вроде понятно, что и как должно выполняться, но транслятор же глаз не имеет :)
все дело в волшебных отступах ;)
Понятно, что ничего не понятно :)
Верно. В Унциях про это ни слова. Ввиду очевидности. Роль привычных {} в питоне играют отступы от левого края.
продолжение не последовало?
В данном случае оператор in сам осуществляет обход списка и поиск элемента. Этот вариант решения будет работать быстрее, чем первый.
Почему оператор in работает быстрее?
Sign up to leave a comment.
Осваиваем Python. Унция 2. Ветвления, циклы + практика.