Примеры идут от простого к сложному: сами операторы и их приоритет, деление и его варианты, ошибки времени выполнения, неизменяемость чисел, виды присваивания и явные преобразования типов. Весь вывод в комментариях получен запуском кода.
Пример 1. Операторы для 7 и 3
Семь базовых арифметических операторов на одной паре чисел.
# 01_operations.py
a = 7
b = 3
print("Сложение:", a + b) # 10
print("Вычитание:", a - b) # 4
print("Умножение:", a * b) # 21
print("Деление:", a / b) # 2.3333333333333335
print("Целочисленное деление:", a // b) # 2
print("Остаток:", a % b) # 1
print("Степень:", a ** b) # 343
Что происходит: / всегда возвращает float, даже когда числа делятся нацело. // и % — парные операции: a == b * (a // b) + a % b.
Пример 2. Приоритет операций
Python считает выражения по обычному математическому приоритету: скобки → степень → умножение/деление////% → сложение/вычитание.
# 02_precedence.py
print(5 + 3 * 2) # 11 — сначала умножение
print((5 + 3) * 2) # 16 — скобки меняют порядок
print(2 * 3 ** 2) # 18 — сначала степень: 3**2=9, потом *2
print(10 / 2 * 3) # 15.0 — при равном приоритете считаем слева направо
print(2 + 3 * 2 ** 2 - 1) # 13
Почему так: при одинаковом приоритете (например, / и *) Python вычисляет выражение слева направо, поэтому 10 / 2 * 3 — это (10 / 2) * 3, а не 10 / (2 * 3).
Пример 3. Деление, типы результата и отрицательные числа
Тип результата зависит от операндов, а целочисленное деление отрицательных чисел округляет не к нулю, а вниз.
# 03_division_types.py
print(8 / 2, type(8 / 2)) # 4.0 <class 'float'>
print(8 // 2, type(8 // 2)) # 4 <class 'int'>
print(8 // 2.0, type(8 // 2.0))# 4.0 <class 'float'>
print(-7 // 2) # -4, а не -3
print(-7 % 2) # 1
Почему так: если хотя бы один операнд — float, результат // тоже становится float. Отрицательное -7 // 2 даёт -4, потому что // округляет результат вниз (к минус бесконечности), а не отбрасывает дробную часть — это частая неожиданность, если ожидать поведения как в языках с усечением к нулю.
Пример 4. ZeroDivisionError
Деление, целочисленное деление и остаток от деления на ноль — все три вызывают исключение.
# 04_zero_division.py
for expr in ["10 / 0", "10 // 0", "10 % 0"]:
try:
eval(expr)
except ZeroDivisionError as error:
print(f"{expr} -> ZeroDivisionError: {error}")
# 10 / 0 -> ZeroDivisionError: division by zero
# 10 // 0 -> ZeroDivisionError: integer division or modulo by zero
# 10 % 0 -> ZeroDivisionError: integer modulo by zero
Что происходит: без обработки исключения такая строка аварийно останавливает программу. Проверка знаменателя перед делением — тема условных конструкций из следующих уроков.
Пример 5. Числа — неизменяемый тип
Выражение num + 2 без присваивания не меняет num: Python создаёт новый объект-число, а старый остаётся как был.
# 05_immutable.py
num = 5
address_1 = id(num)
num + 2
print(num) # 5 — не изменилось
num = num + 2
address_2 = id(num)
print(num) # 7
print("Тот же объект?", address_1 == address_2) # False
Почему так: id() возвращает идентификатор объекта в памяти. После num = num + 2 имя num стало ссылаться на другой объект — число 7, а не на изменённый на месте 5. Изменяемые типы (списки) ведут себя иначе — это станет заметно в теме списков.
Пример 6. Составные присваивания
Компактная запись «взять текущее значение, изменить, сохранить обратно».
# 06_augmented.py
x = 5
x += 3 # x = x + 3
print(x) # 8
x -= 2
print(x) # 6
x *= 4
print(x) # 24
x /= 2
print(x) # 12.0
x //= 2
print(x) # 6.0
x **= 3
print(x) # 216.0
Что происходит: каждый составной оператор — сокращение для «обычная операция + присваивание». Обратите внимание: после x /= 2 тип x стал float и остаётся float дальше, даже если следующая операция — целочисленная по смыслу.
Пример 7. Множественное присваивание, цепочка и обмен значениями
# 07_multiple_assignment.py
a, b, c = 1, 5, 10
print(a, b, c) # 1 5 10
x = y = z = 0 # цепочка: все три получают одно и то же значение
print(x, y, z) # 0 0 0
a, b = 5, 10
a, b = b, a # обмен без временной переменной
print(a, b) # 10 5
Что происходит: в a, b = b, a Python сначала полностью вычисляет правую часть — кортеж (b, a) из старых значений, — и только потом распаковывает его в a и b. Поэтому промежуточная переменная не нужна.
Пример 8. Явное преобразование типов
int(), float(), str(), bool() — четыре функции, которые есть почти в каждой программе.
# 08_conversion.py
print(int("10"), float("10"), str(10), bool(0), bool(1))
# 10 10.0 10 False True
print(int(3.9)) # 3 — обрезает дробную часть, а не округляет
print(int(-3.9)) # -3
print(bool(""), bool("0"), bool([]), bool([0]))
# False True False True — непустая строка "0" истинна!
value = 5
value += 3.14
print(value, type(value)) # 8.14 <class 'float'> — int + float даёт float
Почему так: int() от дробного числа отбрасывает дробную часть в сторону нуля — это не то же самое, что округление: int(3.9) даёт 3, а не 4. Строка "0" непустая, поэтому bool("0") — True, хотя интуитивно кажется, что «ноль» должен быть ложным.
Пример 9. ValueError при неверном преобразовании
# 09_value_error.py
try:
number = int("10.0")
except ValueError as error:
print("ValueError:", error)
# ValueError: invalid literal for int() with base 10: '10.0'
try:
number = float("abc")
except ValueError as error:
print("ValueError:", error)
# ValueError: could not convert string to float: 'abc'
print(float("10.0")) # 10.0 — а float() ту же строку принимает
Что происходит: int() не умеет напрямую разбирать дробную запись в строке — сначала нужно float("10.0"), а затем при необходимости int(float("10.0")). Тип аргумента (строка) подходит, но его содержимое не превращается в нужное число — поэтому это именно ValueError, а не TypeError.
Пример 10. Практика: расчёт сдачи
Собираем несколько операций и преобразование input() в одной прикладной задаче из лекции.
# 10_change.py
price = 250 # int(input("Введите стоимость товара: "))
quantity = 3 # int(input("Введите количество товара: "))
payment = 1000 # int(input("Введите сумму оплаты: "))
total_cost = price * quantity
change = payment - total_cost
print("Сдача:", change, "рублей")
# Сдача: 250 рублей
Что происходит: все три значения из input() — строки, поэтому их обязательно оборачивают в int() до умножения и вычитания; без этого price * quantity либо упадёт с ошибкой, либо (для * со строкой и числом) даст неожиданный результат.
Что делать дальше
Разберите файлы репозитория — там те же идеи в исходном виде, затем переходите к заданиям. Если что-то из примеров не запустилось — сначала загляните в типичные ошибки.