Что такое исключение?
Исключения — это события, которые нарушают нормальный поток выполнения программы. Они возникают, когда программа сталкивается с ошибкой, которую она не может обработать в обычном режиме. Например, попытка деления на ноль или преобразование строки к числу когда она не является числом могут вызвать исключения.
Если говорить доступным языком, то исключения это попытка выполнить то, что у языка выполнить не получится.
Иерархия исключений выглядит вот так:
Это очень примерная картинка, актуальный список всех исключений всегда можно посмотреть вот тут выбрав актуальную для вас версию python.
Начнем со знакомства с самыми обычными исключениями, которые вы увидите в Python. Обратите внимание на то, что ошибка и исключение – два разных слова, описывающих одно и то же в контексте обработки исключений.
Их прям много, детально разберем с чем мы можем столкнуться на данном этапе
Exception – то, на чем фактически строятся все остальные ошибки;
KeyboardInterrupt – возникает, когда пользователь нажимает клавишу прерывания (обычно Delete или Ctrl+C);
NameError – возникает, когда локальное или глобальное имя не найдено;
SyntaxError — возникает, когда синтаксическая ошибка встречается синтаксическим анализатором;
TypeError – возникает, когда операция или функция применяется к объекту несоответствующего типа. Связанное значение
представляет собой строку, в которой приводятся подробные сведения о несоответствии типов;
ValueError – возникает, когда встроенная операция или функция получают аргумент, тип которого правильный, но
неправильно значение, и ситуация не может быть описана более точно, как при возникновении IndexError (Дальше опишу это
человекочитаемым языком, не пугаемся);
ZeroDivisionError – возникает, когда второй аргумент операции division или modulo равен нулю;
По мере изучения разных аспектов и типов данных мы будем разбирать и какие исключения могут с ними произойти
Эта ошибка возникает когда вы пытаетесь обратиться к переменной которой не существует.
some_variable = 123
print(variable_doesnt_exist)Вы увидите ошибку:
NameError: name 'variable_doesnt_exist' is not definedЭта ошибка явно означает, что вам надо проверить имена своих переменных и скорее всего вы или где-то опечатались, или просто явно совершили ошибку.
Эта ошибка возможна в любом случае, когда вы пытаетесь набрать что-либо, что не допустимо в python-е и он вас просто не понимает, не знает что именно ему делать.
5 +
*5Или например:
if:
print('aaa')Вариантов очень много, любые синтаксические ошибки будут вызывать это исключение. (Кстати, из-за чего ошибка в последнем примере?)
Исключение:
SyntaxError: invalid syntax
Это исключение всегда обозначает, что вы где-то не то напечатали, внимательно посмотрите на то место о котором пытается сообщить вам python и постарайтесь исправить ошибку.
Происходит в случае когда вы пытаетесь произвести не допустимые действия с объектами разного типа, например, сложить строку и число
"a" + 5Исключение:
TypeError: can only concatenate str (not "int") to strЭто исключение пока что вы будете видеть только в случае когда пытаетесь преобразовать что-то что невозможно преобразовать. На самом деле это исключение случается гораздо чаще, что вы и увидите при дальнейшем изучении
int("abc")Исключение:
ValueError: invalid literal for int() with base 10: 'abc'Все очень просто, появляется при попытке делить на 0
1 / 0Исключение:
ZeroDivisionError: division by zeroОбработка исключений в Python – это очень просто. Потратим немного времени и напишем несколько примеров, которые их вызовут. Мы начнем с одной из самых элементарных проблем: деление на ноль.
1 / 0За обработку исключений в python отвечают ключевые слова try/except.
try:
1 / 0
except ZeroDivisionError:
print("You cannot divide by zero!")Если мы обратимся к урокам элементарной математики, то вспомним, что на ноль делить нельзя. В Python данная операция вызовет ошибку, как мы можем видеть в примере выше. Чтобы поймать ошибку, мы завернем операцию в оператор try/except.
В блоке try должен выполняться код в котором мы ожидаем какое-либо исключение. И если исключение происходит, то код перестает выполняться, и переходит к блоку/блокам except, и пытается понять произошло ли то исключение, которое описано в блоке except
Блоков except может быть любое количество, так же в одном блоке except может быть больше одного исключения, если вам для разных ошибок нужны одинаковые действия, такие исключения должны быть указаны в скобках и через запятую. Рассмотрим такой пример:
bottles_of_beer = 10
try:
amount_of_people = int(input("Please input amount of people:"))
bottle_per_person = bottles_of_beer / amount_of_people
print(bottle_per_person)
except (ValueError, ZeroDivisionError):
print('Incorrect amount of people!')В этом случае когда мы введем не число, или введем 0, программа продолжит работу, потому что мы обработали исключение и описали что код должен сделать
Или вот такой:
bottles_of_beer = 10
try:
amount_of_people = int(input("Please input amount of people:"))
bottle_per_person = bottles_of_beer / amount_of_people
print(bottle_per_person)
except ValueError:
print('Your input is not a number')
except ZeroDivisionError:
print('You are trying divide to zero')Как и тут, мы тоже все обработали
Комбинировать можно любое количество исключений.
А что произойдет если сделать вот так?
try:
bottles_of_beer = 10
amount_of_people = int(input("Please input amount of people:"))
bottle_per_person = bottles_of_beer / bottles_of_beer
print(bottle_per_person)
except SyntaxError:
print('Your input is not a number')Произойдет следующее, если мы не введем буквы или 0, то ничего страшного, ведь исключение не произошло. А если ввели, то python попытается обработать исключение, но не найдет подходящий эксепшен, и просто завершит программу с ошибкой, как будто исключение и не было обработано
Есть еще один способ поймать ошибку:
try:
1 / 0
except:
print("You cannot divide by zero!")
# ЭТО СРАБОТАЕТ, НО ТАК ДЕЛАТЬ НЕЛЬЗЯНа жаргоне Python это известно как "голое исключение", что означает, что будут найдены вообще все исключения. Причина,
по которой так делать не рекомендуется, заключается в том, что вы не узнаете, что именно за исключение вы выловите.
Когда у вас возникло что-то в духе ZeroDivisionError, вы хотите выявить фрагмент, в котором происходит деление на
ноль. В написанном выше коде вы не можете указать, что именно вам нужно выявить. Хорошие программисты четко указывают
какую ошибку, ожидают, и что с ней делать
Оператор finally очень прост в использовании. Давайте взглянем на нижеизложенный пример:
try:
value = int("ABC")
except ValueError:
print("A ValueError occurred!")
finally:
print("The finally statement has executed!")Что произойдет? Часть finally выполниться вообще всегда, хоть попали в исключение хоть нет.
Оператор try/except также имеет блок else. Он работает только в том случае, если в вашем коде нет ни единой ошибки.
Давайте потратим немного времени и взглянем на парочку примеров:
try:
value = int(input("Please enter value"))
except ValueError:
print("A ValueError occurred!")
else:
print("No error occurred!")В этом примере, если мы введем число, то исключения не случится, и это именно тот случай когда мы попадем в else.
Целиком вся конструкция состоит из 4 блоков
try:
value = int(input("Please enter value"))
except ValueError:
print("A ValueError occurred!")
else:
print("No error occurred!")
finally:
print("The finally statement ran!")В данном коде работают и оператор else, и finally если введете число или except и finally если букву. Большую
часть времени вы не будете сталкиваться с оператором else, используемым в том или ином коде, который следует за
оператором try/except, если ни одна ошибка не была найдена. Единственное полезное применение оператора else, которое
я видел, — это когда вы хотите запустить вторую часть кода, в которой может быть ошибка. Конечно, если ошибка возникает
в else, то она не будет поймана.
Если в вашем коде какие-либо данные не соответствуют вашим ожиданиям, вы всегда можете вызвать исключение, если вам это
необходимо, для этого используется ключевое слово raise.
if odds % 2 != 1:
raise ValueError("Did not get an odd number")Эта конструкция и ключевое слово нам понадобится после того как мы разберем функции, пока я могу показать только одно полезное применение.
Технически всегда можно обработать исключение и вызвать его же еще раз. Зачем такое может быть надо? В случае когда нам не надо предотвращать ошибку, а только записать о том что ошибка случилась (так часто делается), тогда можно записать информацию и вызвать эту же ошибку еще раз
try:
5 / 0
except ZeroDivisionError as e:
raise ZeroDivisionError("Got an error", e)в переменной e будет храниться вся информация об исключении, и таким способом мы вызовем нужный нам тип исключения, с
нашим комментарием и всей системной информацией, делать это через ключевое слово as не обязательно, можно и без этого,
но такой способ дает нам больше возможностей.
В качестве практики нужно взять все задания из прошлых двух лекций и попробовать покрыть весь код возможными исключениями.
Список - это упорядоченная коллекция элементов, которая может содержать объекты разных типов. Они очень полезны при работе с множеством данных.
Вместе со строками в нашу жизнь приходят такие термины как изменяемые и не изменяемые типы данных. Пока что, нам не очень важно знать детали того, что это такое. Но уже необходимо запомнить, что все типы данных в питоне делятся на изменяемые и не изменяемые. Все что мы учили до этого были не изменяемыми типами, а списки изменяемые.
Строки, числа, булеаны (на самом деле булеан вообще является частным случаем числа), не изменяемые, списки изменяемые, это важно! А почему важно узнаете дальше.
Создать список можно, заключив элементы в квадратные скобки [] и разделив их запятыми.
fruits = ['яблоко', 'банан', 'груша', 'апельсин']
numbers = [1, 2, 3, 4, 5]
mixed_list = [1, 'два', 3.0, True]Список может содержать в себе объекты любых типов.
Чтобы получить доступ к элементам списка, используйте индексацию (обращение к элементам по номеру). Нумерация в списках
начинается с 0. Если вам нужен 4-ый элемент коллекции его индекс будет 3. Синтаксис обращения по индексу, через
квадратные скобки []
print(fruits[0]) # Вывод: 'яблоко'
print(numbers[2]) # Вывод: 3Списки можно изменять, например мы можем заменить объект по индексу
fruits[1] = 'киви'
print(fruits) # Вывод: ['яблоко', 'киви', 'груша', 'апельсин']Практически у любого объекта в питоне есть возможность с ним совершить какие-то дополнительные действия. Обычно для этого используются методы (детально мы будем рассматривать эту тему дальше), что бы вызвать какой-либо метод, необходимо обратиться к объекту через точку, указать какой именно метод вам нужен, и если необходимо в скобках указать параметры для этого вызова
obj.method(params) # Параметры не обязательныЧтобы добавить элемент в конец списка, используйте метод append().
fruits.append('ананас')
print(fruits) # Вывод: ['яблоко', 'киви', 'груша', 'апельсин', 'ананас']Чтобы удалить элемент по индексу, используйте del.
del fruits[2]
print(fruits) # Вывод: ['яблоко', 'киви', 'апельсин', 'ананас']Мы уже поговорили про append, но методов у списков гораздо больше, давайте их рассмотрим.
Метод очищает список. Параметров нет.
l = [1, 2, 3]
l.clear()
print(l) # []Метод возвращает копию списка. Параметров нет.
l = [1, 2, 3]
l2 = l.copy()
print(l is l2) # False Вернемся к этому оператору после функций
print(l == l2) # TrueМетод считает сколько раз в списке встречается указанный элемент. Параметр один, что ищем.
l = [1, 2, 3, 1, 1]
print(l.count(1)) # 3
print(l.count(2)) # 1
print(l.count(5)) # 0Метод расширяет список другой коллекцией (пока читаем другим списком). Параметр один, принимает коллекцию (например список).
l1 = [1, 2, 3]
l2 = ['a', 'b']
l1.extend(l2)
print(l1) # [1,2,3,'a','b']Метод возвращает индекс указанного элемента, если элемент не найден, вызывает исключение ValueError. Параметр один, что ищем, можно указать дополнительные параметры через запятую, от какого элемента искать, и до какого.
l = [1, 2, 3]
print(l.index(2)) # 1 - помним что счет начинается с 0
print(l.index(4)) # Вызовет ValueError
l.index(3, 0, 1) # Вызовет ValueError, потому что в списке ограниченном индексами 0 и 1 нет элемента 3Метод добавляет объект на указанное место. Параметра два, на какое место, и какой элемент добавить.
l = [1, 2, 3]
l.insert(1, 4)
print(l) # [1, 4, 2, 3]Поддерживает механику обратных индексов, о ней дальше
Метод "вытаскивает" элемент из указанной позиции, если позиция не указана, вытаскивает последний. Параметр один, позиция элемента и он не обязательный.
l = [1, 2, 3, 4, 5, 6, 7, 8, 9]
last_elem = l.pop()
elem_num_4 = l.pop(3)
print(l) # [1,2,3,5,6,7,8]
print(last_elem) # 9
print(elem_num_4) # 4Поддерживает механику обратных индексов, о ней дальше
Метод удаляет элемент есть находит его в списке. Параметр один, значение элемента.
l = [1, 2, 3, 4, 5, 6, 7, 8, 9]
l.remove(4)
print(l) # [1,2,3,5,6,7,8,9]
l.remove('a') # вызовет ValueErrorМетод разворачивает список. Параметров нет.
l = [1, 2, 3, 4, 5, 6, 7, 8, 9]
l.reverse()
print(l) # [9, 8, 7, 6, 5, 4, 3, 2, 1]Внимание reverse() ничего не возвращает, если сделать
a=l.reverse()в переменной a не будет списка! Измениться оригинал
Метод сортирует список. Параметров два, но детально мы будем его рассматривать в лекции по алгоритмам, там много деталей.
l = [3, 5, 1, 2]
l.sort()
print(l) # [1, 2, 3, 5]Тут тоже меняется оригинал
В случае работы со списками могут произойти ранее не рассмотренное исключения.
IndexError- Случается когда мы пытаемся получить объект по индексу, а такого индекса не существует
l = [1, 2, 3]
print(l[5]) # IndexErrorНа самом деле строки в python-е являются коллекциями, а это значит что к ним применимы многие практики из списков,
например к ним применимы методы count и index
Для доступа к символам строки используйте индексацию, так же как и для списков.
text = "Hello, World!"
print(text[0]) # Вывод: 'H'У строк очень много разных полезных методов, и особенностей, мы рассмотрим только основные, хотя их там много, кто хочет детально почитать про все тыц сюда
Вы можете умножить строку на число, чтобы повторить ее несколько раз.
text = "Привет"
result = text * 3 # Результат: "ПриветПриветПривет"Python предоставляет множество методов для работы со строками. Ниже представлены некоторые из наиболее часто используемых методов.
Метод upper() преобразует все символы строки в верхний регистр, а lower() - в нижний.
text = "Привет, мир!"
uppercase = text.upper() # Результат: "ПРИВЕТ, МИР!"
lowercase = text.lower() # Результат: "привет, мир!"Метод strip() удаляет пробелы и символы перевода строки с начала и конца строки.
text = " Текст с лишними пробелами "
stripped_text = text.strip() # Результат: "Текст с лишними пробелами"Метод split() разбивает строку на список подстрок, используя разделитель.
text = "Яблоки, Груши, Бананы"
fruits = text.split(", ") # Результат: ['Яблоки', 'Груши', 'Бананы']Метод replace() заменяет все вхождения подстроки на другую подстроку.
text = "Привет, мир!"
new_text = text.replace("мир", "вселенная") # Результат: "Привет, вселенная!"Методы find() и index() находят первое вхождение подстроки в строку и возвращают индекс этого вхождения. Разница
между ними в том, что find() возвращает -1, если подстрока не найдена, а index() вызывает исключение.
text = "Это пример текста с примерами"
index1 = text.find("пример") # Результат: 4
index2 = text.index("пример") # Результат: 4
index3 = text.find("нет") # Результат: -1
# index4 = text.index("нет") # Вызовет ValueErrorМетод count() подсчитывает количество вхождений подстроки в строку.
text = "Это пример текста с примерами"
count = text.count("пример") # Результат: 2Методы startswith() и endswith() проверяют, начинается ли строка с указанной подстроки или заканчивается ей.
text = "Это пример текста"
starts_with = text.startswith("Это") # Результат: True
ends_with = text.endswith("текста") # Результат: TrueМетод join() объединяет список строк с помощью текущей строки в качестве разделителя.
fruits = ['Яблоки', 'Груши', 'Бананы']
text = ', '.join(fruits) # Результат: "Яблоки, Груши, Бананы"Split превратит строку в список, join превратит список в строку
Мы обсудили что строки можно конкатенировать. Это далеко не единственная возможность для форматирования строк в python всего их вроде 5, но мы рассмотрим два основных, современный и слегка устаревший, но все еще часто применяемый.
Python 3.6 и выше поддерживают f-строки (f-strings), которые представляют собой удобный способ вставки переменных и выражений в строки. Самый распространенный способ форматирования строк на данный момент
name = "Иван"
age = 30
text = f"Привет, меня зовут {name} и мне {age} лет."
print(text) # Привет, меня зовут Иван и мне 30 лет.F-строки начинаются с буквы f перед открывающей кавычкой, и в фигурных скобках {} можно вставлять переменные или
выражения, которые будут вычислены и подставлены в строку.
name = "Иван"
age = 30
text = "Привет, меня зовут {} и мне {} лет.".format(name, age)
# Результат: "Привет, меня зовут Иван и мне 30 лет."Для его использования вам необходимо указать в строке символы {} для обозначения места куда будут подставлены данные,
и после вызвать метод .format() куда передать значения которые необходимо подставить, кол-во элементов должно
совпадать с количеством скобок. Там довольно много деталей, можете изучить их самостоятельно
Мы будем много использовать оба способа форматирования, а иногда даже сталкиваться с более старыми способами, так что рекомендую разобраться как это работает
Для многих коллекций к которым применим индекс (для нас пока это строки и списки) можно использовать обратный индекс. Что это такое? Это указание индекса от конца к началу.
l = [1, 2, 3]
print(l[-1]) # 3
print(l[-2]) # 2
print(l[-4]) # IndexErrorЭтот инструмент дает довольно много интересных особенностей с которыми мы будем сталкиваться в дальнейшем
Срез позволяет получить часть коллекции из коллекции, чаще всего применяются к строкам или спискам.
Синтаксис среза: строка[начало:конец:шаг].
text = "Hello, World!"
substring = text[2:5] # Получение подстроки "llo"
print(substring) # Вывод: 'llo'
substring = text[7:] # Получение подстроки с 7-го символа до конца
print(substring) # Вывод: 'World!'
substring = text[:5] # Получение подстроки с начала до 5-го символа
print(substring) # Вывод: 'Hello'
substring = text[::2] # Получение каждого второго символа
print(substring) # Вывод: 'Hlo ol!'
copy = text[:] # получение копии строкиСрезы можно комбинировать с обратными индексами!
text = "Hello, World!"
substring = text[:-3] # Получение подстроки "Hello, Wor" (без 3-х последних символов)
substring = text[-3:] # Получение подстроки из 3-х последних символов
print(substring) # Вывод: 'ld!'
substring = text[-5:-1] # Получение 5 последних символов без последнего
print(substring) # Вывод: 'orld'
substring = text[::-1] # Получение строки в обратном порядке
print(substring) # Вывод: '!dlroW ,olleH'Циклы позволяют выполнять повторяющиеся операции.
Цикл for используется для итерации по коллекциям, таким как списки и строки (и не только).
fruits = ['яблоко', 'киви', 'груша', 'апельсин']
for fruit in fruits:
print(fruit)Цикл while выполняется до тех пор, пока условие истинно.
count = 0
while count < 5:
print(count)
count += 1break используется для выхода из цикла досрочно, даже если условие цикла остается истинным. Обычно break
используется внутри условия, чтобы определить момент завершения цикла.
Пример с циклом while:
count = 0
while count < 5:
if count == 3:
break # Выход из цикла, если count равно 3
print(count)
count += 1Пример с циклом for:
fruits = ['яблоко', 'киви', 'груша', 'апельсин']
for fruit in fruits:
if fruit == 'груша':
break # Выход из цикла при нахождении 'груши'
print(fruit)continue используется для перехода к следующей итерации цикла, игнорируя оставшуюся часть текущей итерации.
Обычно continue используется внутри условия для пропуска определенных действий.
Пример с циклом while:
count = 0
while count < 5:
count += 1
if count == 3:
continue # Пропустить вывод числа 3
print(count)Пример с циклом for:
fruits = ['яблоко', 'киви', 'груша', 'апельсин']
for fruit in fruits:
if fruit == 'груша':
continue # Пропустить вывод 'груши'
print(fruit)Ключевые слова break и continue полезны при создании более сложной логики в циклах и позволяют управлять потоком
выполнения программы в более гибком стиле.
Иногда может потребоваться создать бесконечный цикл, который будет выполняться до тех пор, пока его не прервут. Для
этого используется конструкция while True.
while True:
# Этот цикл будет выполняться бесконечно
user_input = input("Введите что-нибудь (для выхода наберите 'q'): ")
if user_input == 'q':
break # Выход из цикла при вводе 'q'Бесконечные циклы могут быть полезными в тех случаях, когда нужно создать программу, которая работает в фоновом режиме и ожидает какого-либо события, либо когда нужно регулярно выполнять какую-то задачу, например, мониторинг сенсоров или сетевых подключений.
Не забывайте, что бесконечные циклы должны иметь какой-то механизм для прерывания, иначе программа будет выполняться бесконечно и может привести к зависанию.
Практика:
-
Создайте список numbers с числами от 1 до 10. Используя цикл for, выведите каждое число из списка numbers, возведенное в квадрат. Используя цикл for, найдите сумму всех чисел в списке numbers.
-
Создайте строку text с произвольным текстом. Используя цикл for, выведите каждый символ из строки text.
-
Используя срезы, выведите первые 5 символов и последние 5 символов из строки text.
-
Создайте список чисел от 1 до 20. Используя цикл for, выведите все числа из списка, которые делятся на 3 без остатка.
-
Используя цикл while, найдите сумму всех чисел от 1 до 100.
-
Создайте бесконечный цикл с использованием while True, который будет предлагать пользователю ввод числа и выводить квадрат этого числа. Добавьте условие для выхода из цикла при вводе значения "0" или "exit".
-
Создайте список слов words, включая некоторые повторяющиеся слова. Используя цикл for, выведите все уникальные слова из списка.
-
Подсчет гласных букв: Попросите пользователя ввести строку текста, а затем используйте методы строк для подсчета количества гласных букв (а, е, и, о, у) в этой строке.
-
Замена слов: Создайте строку, содержащую предложение, и попросите пользователя ввести слово. Затем замените все вхождения этого слова в предложении на слово "заменено". Выведите измененное предложение.
-
Создайте список с повторяющимися элементами. Используйте методы списков для удаления дубликатов и выведите измененный список.
-
Создать список со случайными числами. Найти самое большое и самое маленькое число (пользоваться встроенными методами для их поиска запрещено)
-
FizzBuzz - классическая задача с легких собеседований: Задача заключается в написании программы, которая выводит числа от 1 до n, заменяя некоторые из них на определенные слова в зависимости от их делимости. Условия:
- Программа должна выводить числа от 1 до n (включительно).
- Для чисел, кратных 3, вместо числа должно выводиться слово "Fizz".
- Для чисел, кратных 5, вместо числа должно выводиться слово "Buzz".
- Для чисел, кратных и 3, и 5, вместо числа должно выводиться слово "FizzBuzz".
- Для всех остальных чисел должно выводиться само число.
Пример. Для n = 15 вывод программы должен быть следующим:
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
12.1 сделать так что бы пользователь вводил руками оба делителя и n. Не 3, 5 и 15, а любые числа введенные
пользователем.
