Python с нуля: основы программирования

Курс поможет начать программировать на Python с самого нуля: от установки и первых команд до функций, структур данных и работы с файлами. В конце вы сможете писать небольшие программы и понимать базовую логику кода.

Установка Python и первая программа

Установка Python и первая программа

Эта статья поможет установить Python, проверить, что он работает, и запустить первую программу из файла.

1) Что нужно для старта

Чтобы писать и запускать код на Python, вам понадобятся:

  • Интерпретатор Python (сама программа, которая выполняет ваш код).
  • Редактор кода (можно простой, можно среду разработки).
  • Терминал/командная строка (чтобы проверять установку и запускать файлы).

2) Установка Python

Windows

  1. Скачайте установщик Python с официального сайта (раздел Downloads).
  2. Запустите установщик.
  3. Важно: поставьте галочку “Add python.exe to PATH” (или похожую).
  4. Нажмите Install.

Зачем PATH? PATH — это список папок, где система ищет программы. Если Python добавлен в PATH, вы сможете запускать его командой python из любого места в терминале.

macOS

Обычно удобнее установить актуальную версию Python через официальный установщик (pkg) с сайта Python.

Важно: в macOS может быть предустановлен Python 2/системный Python, но для обучения лучше использовать установленный вами Python 3.

Linux

Во многих дистрибутивах Python 3 уже есть. Если нет — установите через менеджер пакетов вашего дистрибутива (например, apt, dnf, pacman).

3) Проверка установки

Откройте терминал (Windows: PowerShell/Command Prompt; macOS/Linux: Terminal) и выполните:

python --version

или, если на вашей системе Python 3 запускается отдельно:

python3 --version

Вы должны увидеть версию, например Python 3.12.x.

Частые проблемы

  1. Команда python не найдена

    • Windows: скорее всего не добавили Python в PATH. Переустановите Python и включите галочку “Add to PATH”.
    • macOS/Linux: попробуйте python3.
  2. Открывается Microsoft Store (Windows)

    • Значит, система не видит установленный Python в PATH. Проверьте установку и PATH.

4) Первый запуск Python в интерактивном режиме (REPL)

REPL — это режим, где вы вводите команды и сразу видите результат. Запустите:

python

Вы увидите приглашение вроде >>>. Попробуйте:

>>> 2 + 2
4
>>> print("Привет!")
Привет!

Чтобы выйти:

  • Windows: Ctrl + Z, затем Enter
  • macOS/Linux: Ctrl + D

5) Выбор редактора кода

Варианты:

  • IDLE (часто ставится вместе с Python): просто и достаточно для старта.
  • VS Code / PyCharm: мощные инструменты, но могут быть “тяжелее” для первого дня.
  • Любой текстовый редактор: можно, но важно сохранить файл с расширением .py.

Главное на старте — чтобы вы могли создать файл *.py и запустить его.

6) Первая программа в файле

Шаг 1. Создайте папку проекта

Например:

C:\python-start\

или на macOS/Linux:

~/python-start/

Шаг 2. Создайте файл main.py

Содержимое:

print("Привет, мир!")

print(...) — функция, которая выводит текст в консоль.

Шаг 3. Запуск файла

Перейдите в папку с файлом и запустите:

python main.py

Если требуется:

python3 main.py

Вывод:

Привет, мир!

7) Программа с вводом

Добавим ввод имени:

name = input("Как тебя зовут? ")
print("Привет, " + name + "!")

Что здесь происходит:

  • input(...) показывает подсказку и ждёт, пока пользователь введёт текст и нажмёт Enter.
  • введённый текст сохраняется в переменную name.
  • затем мы склеиваем строки через +.

Пример работы:

Как тебя зовут? Аня
Привет, Аня!

8) Важные мелочи, которые экономят время

  1. Не называйте файл python.py (и вообще не используйте имена стандартных модулей: random.py, sys.py). Это может “сломать” импорт в будущем.
  2. Следите за кодировкой: обычно UTF-8 по умолчанию — отлично, кириллица работает.
  3. Запускайте из правильной папки: если терминал “не видит” файл, значит вы не там.

Задания для закрепления

  1. Установите Python и проверьте версию командой python --version (или python3 --version). Напишите, что вывел терминал.
  2. Создайте файл hello.py, который выводит две строки:
    • Привет!
    • Я изучаю Python.
  3. Создайте файл greet.py, который спрашивает имя и город, а затем выводит строку: Привет, <имя> из <город>!.
  4. (Небольшой вызов) В REPL посчитайте:
    • 10 + 25
    • 7 * 8
    • 100 / 4

<details> <summary> Ответы </summary>

  1. Пример корректного ответа (у вас версия может отличаться):
Python 3.12.1
  1. hello.py:
print("Привет!")
print("Я изучаю Python.")
  1. greet.py:
name = input("Введите имя: ")
city = input("Введите город: ")
print("Привет, " + name + " из " + city + "!")
  1. Пример:
>>> 10 + 25
35
>>> 7 * 8
56
>>> 100 / 4
25.0

</details>

Переменные, типы данных и ввод-вывод

Переменные, типы данных и ввод-вывод

В первой статье вы уже запускали программы, использовали print(...) и input(...). Теперь разберём, как хранить данные в программе, какие бывают типы данных и как правильно делать ввод-вывод.

1) Переменные: что это и зачем

Переменная — это имя, под которым программа хранит значение.

age = 12
name = "Аня"

Здесь:

  • age и name — переменные (имена)
  • =оператор присваивания (положить значение в переменную)

Важно: = в программировании не «равно», а именно «присвоить».

Правила именования

  • Имя может содержать буквы, цифры и _, но не может начинаться с цифры.
  • Регистр важен: name и Name — разные переменные.
  • Используйте понятные имена: user_age, total_price.

Примеры:

  • Хорошо: city, user_name, total_sum
  • Плохо: a, x1x1x1, sumSumSUM

2) Типы данных в Python

В Python у каждого значения есть тип. Самые базовые:

Тип Пример Что хранит
int 10, -3 целые числа
float 3.14, 2.0 числа с точкой
str "Привет" текст (строки)
bool True, False логические значения
NoneType None «нет значения»

Проверить тип можно функцией type():

x = 10
print(type(x))  # <class 'int'>

Динамическая типизация

Python позволяет одной и той же переменной в разное время хранить разные типы:

value = 10
value = "десять"

Это удобно, но требует внимательности: вы сами следите, что лежит в переменной.

3) Строки (str) и кавычки

Строку можно записывать в одинарных или двойных кавычках:

text1 = "Привет"
text2 = 'Привет'

Если внутри строки нужна кавычка того же типа — используйте другой тип или экранирование \:

quote = "Он сказал: 'да'"
quote2 = 'Он сказал: \'да\''

4) Ввод: input() всегда возвращает строку

input() всегда возвращает значение типа str, даже если пользователь ввёл число.

s = input("Введите что-нибудь: ")
print(type(s))

Если вы ждёте число, нужно преобразование.

Преобразование типов

  • int("12")12
  • float("3.14")3.14
  • str(10) → "10"

Пример: попросим возраст и прибавим 1.

age = int(input("Введите возраст: "))
print(age + 1)

Если ввести не число (например, abc), будет ошибка ValueError.

5) Вывод: print() и полезные настройки

print() может выводить несколько значений за раз:

name = "Аня"
age = 12
print(name, age)

По умолчанию между аргументами ставится пробел. Это можно изменить параметром sep:

print("a", "b", "c", sep="-")  # a-b-c

И можно управлять окончанием строки параметром end (по умолчанию \n — перенос строки):

print("Привет", end="")
print("!" )
# выведет: Привет!

6) Склейка строк и форматирование

Склейка через +

name = "Аня"
print("Привет, " + name + "!")

Но важно: строки и числа так складывать нельзя.

age = 12
# print("Возраст: " + age)  # TypeError

Исправления:

print("Возраст: " + str(age))

f-строки (самый удобный способ)

name = "Аня"
age = 12
print(f"Привет, {name}! Тебе {age} лет.")

В фигурных скобках {...} можно писать переменные и даже выражения:

x = 5
print(f"x*2 = {x * 2}")

7) Мини-пример: диалог с пользователем

name = input("Имя: ")
city = input("Город: ")
year = int(input("Год рождения: "))

age = 2026 - year
print(f"Привет, {name} из {city}! Тебе примерно {age} лет.")

Комментарий:

  • year преобразуем через int(...), иначе вычитание не сработает.
  • age — результат вычисления, сохраняем в переменную, чтобы не повторять формулу.

Задания для закрепления

  1. Создайте переменные a = 7 и b = 3. Выведите:
  • их сумму
  • их произведение
  1. Пользователь вводит длину и ширину прямоугольника (как числа с точкой). Выведите периметр.

  2. Пользователь вводит своё имя и любимое число (целое). Выведите фразу в формате f-строки: Имя: <имя>, любимое число: <число>.

  3. Что выведет этот код? (ответ текстом)

x = input("Введите x: ")
print(x + "5")

<details> <summary> Ответы </summary>

a = 7
b = 3
print(a + b)  # 10
print(a * b)  # 21
  1. Периметр: P=2(длина+ширина)P = 2\cdot(\text{длина} + \text{ширина}). Здесь:
  • длина и ширина — введённые числа
  • + складывает их
  • умножение на 2 даёт сумму всех сторон
length = float(input("Длина: "))
width = float(input("Ширина: "))
perimeter = 2 * (length + width)
print(perimeter)
name = input("Имя: ")
fav = int(input("Любимое число: "))
print(f"Имя: {name}, любимое число: {fav}")
  1. input() возвращает строку. Поэтому x + "5" — это склейка строк. Например, если ввести 12, будет выведено:
125

</details>

Условия и циклы: управление логикой

Условия и циклы: управление логикой

Программа становится «умной», когда умеет:

  1. Принимать решения (выполнять разные ветки кода).
  2. Повторять действия (делать одно и то же много раз).

В Python за это отвечают условия (if) и циклы (for, while).

1) Условия: if / elif / else

Базовая форма:

age = 17

if age >= 18:
    print("Доступ открыт")
else:
    print("Доступ закрыт")

Главное правило: код внутри ветки должен быть с отступом (обычно 4 пробела).

elif: несколько вариантов

score = 82

if score >= 90:
    grade = "A"
elif score >= 75:
    grade = "B"
elif score >= 60:
    grade = "C"
else:
    grade = "D"

print(grade)

Как это читается:

если score >= 90 -> A
иначе если score >= 75 -> B
иначе если score >= 60 -> C
иначе -> D

2) Сравнения и логические операторы

Часто используемые сравнения:

  • == равно
  • != не равно
  • <, <=, >, >=

Логические операторы:

  • and — оба условия истинны
  • or — хотя бы одно истинно
  • not — отрицание

Пример с несколькими условиями:

temp = 21
is_raining = False

if temp >= 20 and not is_raining:
    print("Можно идти гулять")
else:
    print("Лучше остаться дома")

Частая ошибка: сравнение вместо присваивания

  • = — присваивание
  • == — сравнение
x = 10
if x == 10:
    print("x равен 10")

3) Вложенные условия и «ранний выход»

Иногда условие внутри условия читается тяжело:

age = 20
has_ticket = True

if age >= 18:
    if has_ticket:
        print("Проходите")
    else:
        print("Нужен билет")
else:
    print("Нельзя")

Часто проще объединить логикой:

if age >= 18 and has_ticket:
    print("Проходите")
else:
    print("Нельзя")

4) Цикл while: повторяем, пока условие истинно

while удобен, когда неизвестно заранее, сколько будет повторений.

count = 3

while count > 0:
    print(count)
    count -= 1

print("Старт!")

Важно: внутри while обычно должно что-то менять условие, иначе получится бесконечный цикл.

break и continue

  • break — выйти из цикла сразу
  • continue — пропустить остаток текущей итерации и перейти к следующей
n = 0

while True:
    n += 1

    if n == 2:
        continue  # пропустим вывод для 2

    print(n)

    if n == 5:
        break  # закончим на 5

5) Цикл for: перебор последовательностей

for удобен, когда есть набор значений для перебора.

range() — генератор чисел

for i in range(5):
    print(i)

Выведет числа от 0 до 4.

Полезные формы:

range(5)        # 0..4
range(2, 6)     # 2..5
range(10, 0, -2)  # 10, 8, 6, 4, 2

Пример: сумма чисел от 1 до 100:

total = 0
for x in range(1, 101):
    total += x
print(total)

6) else у циклов (редко, но полезно)

У циклов бывает else: он выполняется только если цикл завершился без break.

numbers = [3, 5, 7, 9]

for x in numbers:
    if x % 2 == 0:
        print("Нашли чётное")
        break
else:
    print("Чётных нет")

Здесь else сработает, потому что break не был выполнен.

7) Типичные ошибки новичков

  1. Неправильные отступы
# так нельзя
if True:
print("hi")
  1. Путают границы range: range(5) не включает 5.

  2. Бесконечный while: забыли изменить переменную, влияющую на условие.


Задания для закрепления

  1. Пользователь вводит целое число. Выведите:
  • "Положительное", если число > 0
  • "Отрицательное", если число < 0
  • "Ноль", если число равно 0
  1. Пользователь вводит пароль. Если пароль равен строке "python", вывести "Доступ", иначе "Ошибка".

  2. Дано число n (ввод). Выведите сумму чисел от 1 до n включительно с помощью for.

  3. Выведите все числа от 10 до 1 (включительно) с шагом -1.

  4. Пользователь вводит числа по одному. Как только введёт 0 — остановиться и вывести, сколько чисел было введено до нуля.

  5. Дан список:

nums = [4, 7, 9, 10, 13]

Найдите первое чётное число и выведите его. Если чётных нет — выведите "нет".

<details> <summary> Ответы </summary>

x = int(input("Введите число: "))

if x > 0:
    print("Положительное")
elif x < 0:
    print("Отрицательное")
else:
    print("Ноль")
pwd = input("Пароль: ")

if pwd == "python":
    print("Доступ")
else:
    print("Ошибка")
n = int(input("n: "))

s = 0
for i in range(1, n + 1):
    s += i

print(s)
for x in range(10, 0, -1):
    print(x)
count = 0

while True:
    x = int(input("Введите число (0 — стоп): "))
    if x == 0:
        break
    count += 1

print(count)
nums = [4, 7, 9, 10, 13]

for x in nums:
    if x % 2 == 0:
        print(x)
        break
else:
    print("нет")

</details>

Списки, словари и другие структуры данных

Списки, словари и другие структуры данных

Когда данных становится больше одного значения, переменных уже не хватает. Нужны структуры данных: они помогают хранить наборы значений, быстро находить нужное и удобно перебирать элементы (про перебор через for/while см. статью про циклы).

1) Список (list): упорядоченная коллекция

Список хранит элементы в определённом порядке и позволяет изменять содержимое.

nums = [10, 20, 30]
words = ["привет", "мир"]
mixed = [1, "два", True]

Индексы и срезы

  • Индексация начинается с 0.
  • Отрицательные индексы — с конца.
nums = [10, 20, 30, 40]
print(nums[0])   # 10
print(nums[-1])  # 40

print(nums[1:3]) # [20, 30]
print(nums[:2])  # [10, 20]
print(nums[2:])  # [30, 40]

Частые операции со списками

nums = [10, 20, 30]

nums.append(40)      # добавить в конец
nums.insert(1, 15)   # вставить по индексу

x = nums.pop()       # удалить и вернуть последний
nums.remove(20)      # удалить первое вхождение значения

print(len(nums))     # размер списка
print(15 in nums)    # проверка наличия

remove(value) выдаст ошибку, если значения нет. Если не уверены — проверяйте через in.

Список внутри списка (вложенность)

matrix = [
    [1, 2, 3],
    [4, 5, 6]
]
print(matrix[1][2])  # 6

Важный момент: изменяемость (mutability)

Списки изменяемы. Это влияет на присваивание:

a = [1, 2]
b = a
b.append(3)
print(a)  # [1, 2, 3]  (изменился и a)

Если нужна независимая копия списка (поверхностная):

a = [1, 2]
b = a.copy()   # или b = a[:]

2) Кортеж (tuple): как список, но неизменяемый

Кортеж похож на список, но его нельзя менять (удобно для «фиксированных» наборов).

point = (3, 5)
# point[0] = 10  # нельзя

Часто кортежи используют для распаковки:

a, b = (10, 20)
print(a, b)

3) Словарь (dict): ключ → значение

Словарь хранит пары: ключ и соответствующее значение.

user = {
    "name": "Аня",
    "age": 12,
    "city": "Казань"
}

print(user["name"])  # Аня

Добавление и изменение

user["age"] = 13
user["email"] = "anya@mail.com"

Безопасное чтение: get

Если ключа нет, user["x"] даст ошибку. Часто удобнее:

print(user.get("phone"))           # None
print(user.get("phone", "нет"))  # нет

Перебор словаря

for key in user:
    print(key, user[key])

for key, value in user.items():
    print(key, value)

Удаление

user.pop("city")
del user["email"]

Ключами в словаре обычно делают строки или числа. Главное требование: ключ должен быть неизменяемым (например, список ключом быть не может).

4) Множество (set): уникальные элементы без порядка

set хранит только уникальные значения и хорошо подходит для проверки «уже встречалось ли».

s = {1, 2, 2, 3}
print(s)  # {1, 2, 3}

s.add(4)
print(3 in s)  # True

Полезные операции:

a = {1, 2, 3}
b = {3, 4}

print(a | b)  # объединение: {1, 2, 3, 4}
print(a & b)  # пересечение: {3}
print(a - b)  # разность: {1, 2}

5) Как выбрать структуру

  • list — важен порядок, нужны дубликаты, часто добавляете/удаляете.
  • tuple — набор фиксирован, менять не нужно.
  • dict — нужно быстро находить значение по ключу (например, «имя → телефон»).
  • set — важна уникальность и быстрый поиск «есть ли элемент».

Задания для закрепления

  1. Дан список nums = [3, 1, 3, 5, 1]. Создайте множество уникальных значений и выведите его.

  2. Пользователь вводит 3 слова. Сохраните их в список и выведите второе слово.

  3. Дан словарь:

product = {"name": "Чай", "price": 120}
  • Добавьте ключ "in_stock" со значением True
  • Увеличьте price на 30
  • Выведите все пары ключ-значение через items()
  1. Есть список имён: names = ["Аня", "Борис", "Аня", "Дима", "Борис"]. Посчитайте, сколько раз встречается каждое имя, и сохраните результат в словарь вида {"Аня": 2, ...}.

  2. (Небольшой вызов) Дан список чисел. Создайте новый список из квадратов только чётных чисел.

<details> <summary> Ответы </summary>

nums = [3, 1, 3, 5, 1]
unique = set(nums)
print(unique)
words = []
for _ in range(3):
    words.append(input("Введите слово: "))

print(words[1])
product = {"name": "Чай", "price": 120}

product["in_stock"] = True
product["price"] += 30

for k, v in product.items():
    print(k, v)
names = ["Аня", "Борис", "Аня", "Дима", "Борис"]
counts = {}

for name in names:
    # если ключа нет, берём 0
    counts[name] = counts.get(name, 0) + 1

print(counts)
nums = [1, 2, 3, 4, 5, 6]
result = []

for x in nums:
    if x % 2 == 0:
        result.append(x * x)

print(result)  # [4, 16, 36]

</details>

Функции и основы модульности кода

Функции и основы модульности кода

Когда программа становится больше пары десятков строк, появляются две проблемы:

  • один и тот же код начинает повторяться;
  • код трудно читать и тестировать, потому что всё «свалено» в одном месте.

Функции решают первую проблему, а модульность (разделение по файлам и логическим частям) — вторую.

1) Функция: что это

Функция — это именованный блок кода, который можно вызывать много раз.

Простейший пример:

def greet():
    print("Привет!")

greet()
greet()

Важно:

  • def создаёт функцию.
  • Код внутри функции имеет отступ.
  • Функция не выполняется, пока вы её не вызвали: greet().

2) Параметры и аргументы

Функции могут принимать данные через параметры:

def greet(name):
    print(f"Привет, {name}!")

greet("Аня")

Термины:

  • параметр — переменная в определении (name);
  • аргумент — конкретное значение при вызове ("Аня").

Несколько параметров

def rectangle_area(width, height):
    return width * height

3) return: как функция отдаёт результат

print() показывает текст на экране, но не возвращает результат для дальнейших вычислений.

Для результата используется return:

def add(a, b):
    return a + b

result = add(2, 3)
print(result)  # 5

Правила return:

  • после return функция завершается сразу;
  • если return не написан, функция возвращает None.

4) Функция как «мини-программа»: разделяйте ответственность

Хорошая привычка: одна функция — одна понятная задача.

Плохо (смешали ввод, вычисления и вывод):

# пример того, как НЕ стоит делать
# def calc():
#     ...

Лучше разделить:

def read_int(prompt):
    return int(input(prompt))

def sum_to_n(n):
    total = 0
    for i in range(1, n + 1):
        total += i
    return total

n = read_int("n: ")
print(sum_to_n(n))

Циклы и условия вы уже знаете (см. прошлую статью про управление логикой) — здесь важно, что они «живут» внутри функций так же, как и в обычном коде.

5) Значения по умолчанию и именованные аргументы

Параметр по умолчанию

def greet(name, city="неизвестно"):
    print(f"Привет, {name}! Город: {city}")

greet("Аня")
greet("Аня", "Казань")

Именованные аргументы (keyword arguments)

Можно явно указать, какой параметр вы передаёте:

greet(city="Москва", name="Борис")

Это повышает читаемость, особенно когда параметров много.

6) Область видимости: где «живут» переменные

Переменные, созданные внутри функции, обычно доступны только внутри неё.

def f():
    x = 10
    return x

# print(x)  # так нельзя: x вне функции не существует

Если снаружи есть переменная с тем же именем — это другое значение:

x = 5

def f():
    x = 10
    return x

print(f())  # 10
print(x)    # 5

7) Докстроки: короткое описание функции

Докстрока — строка в начале функции в тройных кавычках. Её удобно читать в подсказках редактора.

def is_even(n):
    """Возвращает True, если число n чётное."""
    return n % 2 == 0

8) Модульность: разделяем проект на файлы

В Python каждый файл .py — модуль.

Пример структуры:

project/
  main.py
  utils.py

utils.py:

def clamp(x, low, high):
    if x < low:
        return low
    if x > high:
        return high
    return x

main.py:

from utils import clamp

score = int(input("Введите оценку: "))
score = clamp(score, 0, 100)
print(score)

Зачем это нужно

  • проще ориентироваться: «утилиты» отдельно, «логика запуска» отдельно;
  • легче переиспользовать: модуль можно подключить в другой программе;
  • меньше риска повторять один и тот же код (DRY — Don’t Repeat Yourself).

9) Блок запуска: if __name__ == "__main__"

Иногда модуль содержит и функции, и небольшой «запускной» код для проверки.

def add(a, b):
    return a + b

if __name__ == "__main__":
    print(add(2, 3))

Смысл:

  • если файл запустили напрямую, код в этом блоке выполнится;
  • если файл импортировали, блок не выполнится.

Задания для закрепления

  1. Напишите функцию multiply(a, b), которая возвращает произведение.

  2. Напишите функцию safe_int(text), которая пытается превратить строку в число:

  • если получается, возвращает int;
  • если нет, возвращает None.

Подсказка: используйте try/except.

  1. Напишите функцию count_words(s), которая возвращает количество слов в строке. Считайте, что слова разделены пробелами.

  2. Разбейте код на модули:

  • создайте файл math_utils.py с функцией is_even(n);
  • в main.py импортируйте is_even и выведите "чётное" или "нечётное" для введённого числа.

<details> <summary> Ответы </summary>

def multiply(a, b):
    return a * b
def safe_int(text):
    try:
        return int(text)
    except ValueError:
        return None
def count_words(s):
    # простой вариант для начала: разделяем по пробелам
    parts = s.split()
    return len(parts)

math_utils.py:

def is_even(n):
    return n % 2 == 0

main.py:

from math_utils import is_even

n = int(input("Введите число: "))

if is_even(n):
    print("чётное")
else:
    print("нечётное")

</details>

Работа с файлами и обработка ошибок

Работа с файлами и обработка ошибок

Файлы позволяют программе сохранять данные между запусками: результаты, заметки, настройки. А обработка ошибок помогает делать программы устойчивыми: не падать из‑за «неправильного ввода» или отсутствующего файла.

1) Пути к файлам: где Python ищет файл

Если вы пишете просто имя файла ("data.txt"), Python ищет его в текущей рабочей папке (той, из которой вы запускаете программу).

Чтобы избежать путаницы:

  1. Храните файлы рядом с вашим main.py (особенно на старте).
  2. Явно печатайте, где вы находитесь:
import os
print(os.getcwd())

2) Открытие файла: open() и режимы

Работа с файлом начинается с open(path, mode, encoding=...).

Частые режимы:

  • "r" — чтение (если файла нет, будет ошибка)
  • "w" — запись (создаст файл или перезапишет существующий)
  • "a" — дозапись в конец (создаст файл, если его нет)

Для текстовых файлов почти всегда указывайте кодировку:

f = open("notes.txt", "r", encoding="utf-8")

Но вручную закрывать файл легко забыть — лучше использовать with.

3) Контекстный менеджер with: файл закроется сам

with open("notes.txt", "r", encoding="utf-8") as f:
    text = f.read()

print(text)

Плюс with: даже если внутри произойдёт ошибка, файл корректно закроется.

4) Чтение файла: read, readline, readlines, перебор строк

Прочитать весь файл целиком

with open("notes.txt", "r", encoding="utf-8") as f:
    text = f.read()

print(text)

Удобно для небольших файлов.

Читать построчно (экономно по памяти)

with open("notes.txt", "r", encoding="utf-8") as f:
    for line in f:
        print(line)

Часто строка заканчивается символом перевода строки \n, поэтому print(line) может давать «пустые строки». Обычно делают так:

with open("notes.txt", "r", encoding="utf-8") as f:
    for line in f:
        print(line.rstrip())  # убрали пробелы/\n справа

5) Запись в файл: write и writelines

Перезаписать файл

with open("out.txt", "w", encoding="utf-8") as f:
    f.write("Первая строка\n")
    f.write("Вторая строка\n")

Важно: write() не добавляет перенос строки сам\n нужно писать явно.

Дописать в конец

with open("out.txt", "a", encoding="utf-8") as f:
    f.write("Ещё одна строка\n")

6) Обработка ошибок: try/except

Ошибки бывают «ожидаемые»:

  • файла нет (FileNotFoundError)
  • нет прав на запись (PermissionError)
  • строка не превращается в число (ValueError)

Чтобы программа не завершалась аварийно, используйте try/except:

try:
    with open("data.txt", "r", encoding="utf-8") as f:
        text = f.read()
except FileNotFoundError:
    print("Файл не найден")

Несколько except

try:
    n = int(input("Введите число: "))
    print(10 / n)
except ValueError:
    print("Нужно ввести целое число")
except ZeroDivisionError:
    print("На ноль делить нельзя")

Подробный ввод‑вывод и преобразования типов были в статье про переменные и input() — здесь важно, что ошибки конвертации удобно ловить через ValueError.

else и finally

  • else выполняется, если ошибок не было
  • finally выполняется всегда (например, чтобы вывести «завершение»)
try:
    with open("data.txt", "r", encoding="utf-8") as f:
        text = f.read()
except FileNotFoundError:
    print("Нет файла")
else:
    print("Прочитали успешно")
    print(text)
finally:
    print("Готово")

7) Практический мини-пример: «лог» действий

Идея: пользователь вводит строку, программа записывает её в файл. Если файл нельзя открыть — аккуратно сообщает.

msg = input("Сообщение для лога: ")

try:
    with open("log.txt", "a", encoding="utf-8") as f:
        f.write(msg + "\n")
except PermissionError:
    print("Нет прав на запись в файл")
else:
    print("Записано")

Задания для закрепления

  1. Создайте файл hello_file.txt и запишите в него две строки: Привет и Это файл.

  2. Прочитайте hello_file.txt и выведите его содержимое на экран.

  3. Пользователь вводит 3 строки. Запишите их в файл lines.txt, по одной строке на строку.

  4. Прочитайте lines.txt построчно и выведите строки без лишних пустых строк.

  5. Напишите код, который пытается прочитать файл missing.txt. Если файла нет — вывести "Файл missing.txt не найден" (без падения программы).

  6. Пользователь вводит число. Выведите 100 / n. Обработайте две ошибки: неверный ввод и деление на ноль.

<details> <summary> Ответы </summary>

with open("hello_file.txt", "w", encoding="utf-8") as f:
    f.write("Привет\n")
    f.write("Это файл\n")
with open("hello_file.txt", "r", encoding="utf-8") as f:
    text = f.read()

print(text)
with open("lines.txt", "w", encoding="utf-8") as f:
    for _ in range(3):
        s = input("Строка: ")
        f.write(s + "\n")
with open("lines.txt", "r", encoding="utf-8") as f:
    for line in f:
        print(line.rstrip())
try:
    with open("missing.txt", "r", encoding="utf-8") as f:
        print(f.read())
except FileNotFoundError:
    print("Файл missing.txt не найден")
try:
    n = int(input("n: "))
    print(100 / n)
except ValueError:
    print("Нужно ввести целое число")
except ZeroDivisionError:
    print("На ноль делить нельзя")

</details>

Итоговый мини-проект: программа на Python

Итоговый мини-проект: программа на Python

Мини-проект — это способ собрать вместе то, что вы уже умеете: переменные, условия, циклы, структуры данных, функции, модули, файлы и обработку ошибок. Сделаем небольшую, но «настоящую» консольную программу: список дел (ToDo) с сохранением в файл.

1) Что должна уметь программа

Функциональность (минимум):

  1. Показать список дел.
  2. Добавить дело.
  3. Отметить дело выполненным.
  4. Удалить дело.
  5. Сохранять дела в файл и загружать при старте.

Команды будем вводить текстом (например: add, list, done, delete, exit).

2) Формат хранения данных (простой текст)

Чтобы не усложнять, сохраним каждое дело отдельной строкой в файле tasks.txt.

Формат строки:

  • id — целое число
  • done0 (не выполнено) или 1 (выполнено)
  • text — описание

Разделитель — символ |.

Пример файла:

1|0|Купить хлеб
2|1|Сделать домашку

В программе будем хранить задачи как список словарей:

tasks = [
    {"id": 1, "done": False, "text": "Купить хлеб"},
    {"id": 2, "done": True,  "text": "Сделать домашку"}
]

3) План: разложим на функции

Вместо «монолита» сделаем набор понятных функций:

  • load_tasks(path) — прочитать файл и вернуть список задач
  • save_tasks(path, tasks) — записать список задач в файл
  • print_tasks(tasks) — аккуратно вывести
  • add_task(tasks, text) — добавить
  • mark_done(tasks, task_id) — отметить выполненной
  • delete_task(tasks, task_id) — удалить

Технику with open(...) и обработку ошибок try/except смотрите в статье «Работа с файлами и обработка ошибок»; ниже — готовое применение.

4) Реализация (вариант в одном файле)

Создайте main.py рядом с tasks.txt (или программа сама создаст файл при сохранении).

TASKS_FILE = "tasks.txt"

def load_tasks(path):
    tasks = []
    try:
        with open(path, "r", encoding="utf-8") as f:
            for line in f:
                line = line.rstrip()
                if not line:
                    continue
                parts = line.split("|", 2)
                if len(parts) != 3:
                    continue  # пропускаем «битые» строки

                task_id = int(parts[0])
                done = parts[1] == "1"
                text = parts[2]

                tasks.append({"id": task_id, "done": done, "text": text})
    except FileNotFoundError:
        # файла нет — начнём с пустого списка
        return []
    except ValueError:
        # где-то не получилось превратить id в число
        return []

    return tasks

def save_tasks(path, tasks):
    with open(path, "w", encoding="utf-8") as f:
        for t in tasks:
            done_flag = "1" if t["done"] else "0"
            f.write(f"{t['id']}|{done_flag}|{t['text']}\n")

def next_id(tasks):
    if not tasks:
        return 1
    return max(t["id"] for t in tasks) + 1

def print_tasks(tasks):
    if not tasks:
        print("Список пуст")
        return

    for t in tasks:
        mark = "[x]" if t["done"] else "[ ]"
        print(f"{mark} {t['id']}: {t['text']}")

def add_task(tasks, text):
    text = text.strip()
    if not text:
        print("Пустое дело не добавляем")
        return

    tasks.append({"id": next_id(tasks), "done": False, "text": text})
    print("Добавлено")

def find_task(tasks, task_id):
    for t in tasks:
        if t["id"] == task_id:
            return t
    return None

def mark_done(tasks, task_id):
    t = find_task(tasks, task_id)
    if t is None:
        print("Нет задачи с таким id")
        return
    t["done"] = True
    print("Отмечено выполненным")

def delete_task(tasks, task_id):
    for i, t in enumerate(tasks):
        if t["id"] == task_id:
            tasks.pop(i)
            print("Удалено")
            return
    print("Нет задачи с таким id")

def main():
    tasks = load_tasks(TASKS_FILE)

    print("ToDo. Команды: list, add, done, delete, save, exit")

    while True:
        cmd = input("> ").strip().lower()

        if cmd == "list":
            print_tasks(tasks)

        elif cmd == "add":
            text = input("Текст задачи: ")
            add_task(tasks, text)

        elif cmd == "done":
            try:
                task_id = int(input("id задачи: "))
            except ValueError:
                print("id должен быть числом")
                continue
            mark_done(tasks, task_id)

        elif cmd == "delete":
            try:
                task_id = int(input("id задачи: "))
            except ValueError:
                print("id должен быть числом")
                continue
            delete_task(tasks, task_id)

        elif cmd == "save":
            save_tasks(TASKS_FILE, tasks)
            print("Сохранено")

        elif cmd == "exit":
            save_tasks(TASKS_FILE, tasks)
            print("Пока!")
            break

        else:
            print("Неизвестная команда")

if __name__ == "__main__":
    main()

5) Проверка: пример сессии

ToDo. Команды: list, add, done, delete, save, exit
> list
Список пуст
> add
Текст задачи: Купить хлеб
Добавлено
> add
Текст задачи: Сделать домашку
Добавлено
> list
[ ] 1: Купить хлеб
[ ] 2: Сделать домашку
> done
id задачи: 2
Отмечено выполненным
> list
[ ] 1: Купить хлеб
[x] 2: Сделать домашку
> exit
Пока!

6) Как улучшить проект (без переписывания всего)

  1. Добавить команду stats (сколько всего / сколько сделано).
  2. Разрешить add Купить хлеб в одну строку (разбор команды).
  3. Вынести функции чтения/записи в отдельный модуль storage.py, а интерфейс оставить в main.py (см. статью про модульность).

Задания для закрепления

  1. Добавьте команду stats, которая выводит:
  • всего задач
  • выполнено
  • осталось
  1. Сделайте команду undone, которая снимает отметку выполненности по id.

  2. Сделайте команду search: пользователь вводит слово, программа выводит только те задачи, где слово встречается в тексте (без учёта регистра).

  3. (Небольшой вызов) Сделайте автосохранение: после add/done/delete/undone файл сохраняется автоматически.

<details> <summary> Ответы </summary>

  1. stats
def stats(tasks):
    total = len(tasks)
    done = sum(1 for t in tasks if t["done"])
    left = total - done
    print(f"Всего: {total}, выполнено: {done}, осталось: {left}")

В main():

elif cmd == "stats":
    stats(tasks)
  1. undone
def mark_undone(tasks, task_id):
    t = find_task(tasks, task_id)
    if t is None:
        print("Нет задачи с таким id")
        return
    t["done"] = False
    print("Снята отметка выполнения")

В main() добавьте ветку по аналогии с done.

  1. search
def search(tasks, query):
    q = query.strip().lower()
    if not q:
        print("Пустой запрос")
        return

    found = []
    for t in tasks:
        if q in t["text"].lower():
            found.append(t)

    print_tasks(found)
  1. Автосохранение: после изменения списка вызывайте save_tasks.

Например, после добавления:

elif cmd == "add":
    text = input("Текст задачи: ")
    add_task(tasks, text)
    save_tasks(TASKS_FILE, tasks)

То же самое после done/delete/undone.

</details>