Є else
і finally
розділи виключень, що обробляють надлишки? Наприклад, чи є різниця між наступними двома фрагментами коду?
try:
foo = open("foo.txt")
except IOError:
print("error")
else:
print(foo.read())
finally:
print("finished")
і
try:
foo = open("foo.txt")
print(foo.read())
except IOError:
print("error")
print("finished")
Більш загально, не можна вмісту else
завжди переміщуватися в try
, і не можна вміст finally
просто перенести за межі блоку спробувати / ловити? Якщо так, то яка мета else
і finally
? Це просто для підвищення читабельності?
Відповіді:
50 для відповіді № 1Ідея полягає в тому, щоб ви зберігали код, для якого ви обробляєте винятки, якомога менше. Що-небудь в else
блок міг переїхати в try
, так, але тоді ви, можливо, захочете виняток, коли дійсно хочете, щоб його підняли. Можливо, ви успішно відкрили файл, але якщо read
викликає IOError
і це "в try
, що теж буде спіймано.
Від кінський рот:
Використання
else
пункт краще, ніж додавання додаткового коду доtry
застереження, оскільки це дозволяє уникнути випадкового потрапляння на виняток, який не був порушений кодом, захищенимtry ... except
заява
Як вже було сказано в двох інших відповідях finally
блок є для коду, який буде виконуватися незалежно від того, піднято виняток де завгодно, у тому числі всередині else
або except
та чи обробляється цей виняток чи ні. Канонічний випадок використання для цього забезпечує абсолютно впевненість, що ручка файлу закрита, незалежно від того. *
The офіційне фразування це:
Коли виняток стався в
try
пункт, і його не оброблялиexcept
пункт (або це сталося в aexcept
абоelse
пункт), воно повторно піднімається післяfinally
пункт виконується. Thefinally
Стаття також виконується "на виході", коли будь-яке інше положенняtry
Заява залишається черезbreak
,continue
, абоreturn
заява
* Це конкретно використання було дещо заперечене менеджерами контексту (with...as
блоки).
34 за відповідь № 2
finally
виконується незалежно від того, чи не вдаються або успішні висловлювання у блоці спробу. else
виконується лише в тому випадку, якщо висловлювання у блоці спробу не створюють винятку.
10 за відповідь № 3
Незалежно від того, що станеться, блок в finally
завжди отримує страту. Навіть якщо виняток не оброблявся або обробники винятків генерували нові винятки.
7 для відповіді № 4
Якщо ви перемістите вміст else
блок всередині try
блоку, ви також будете ловити винятки, які можуть статися під час else
блок. Якщо рядок
print(foo.read())
у вашому прикладі викидає IOError
, ваш перший фрагмент коду не здобуде помилку, тоді як ваш другий фрагмент буде try
як можна менше блоків, щоб насправді виловлювати лише ті винятки, які ви хочете спіймати.
The finally
блок завжди виконується, незалежно від того. Якщо, наприклад, try
блок містить a return
заява, а finally
блок все одно буде виконуватися, тоді як будь-який код під цілим try
/except
блок виграв "т.