Переменные и типы данных: как программа хранит информацию
В прошлой статье вы запустили первую программу и увидели, как компьютер печатает текст на экран. Это уже настоящая программа, но пока она делает ровно одно и то же при каждом запуске. Чтобы программа стала полезной, ей нужно запоминать — имя пользователя, сумму в корзине, счёт в игре, ответ на вопрос. Всё, что программа помнит во время работы, живёт в переменных.
Эта статья — про то, что такое переменная, чем «строка» отличается от «числа» и почему компьютер иногда отказывается складывать две вещи, которые вам кажутся совершенно складываемыми.
Если что-то не получится с первого раза — это нормально. Здесь буквально всё разбирается по шагам, и каждый пример можно набрать руками и запустить.
Зачем вообще что-то хранить
Представьте, что вы считаете стоимость заказа. Вы говорите вслух: «Так, кофе — 250 рублей, круассан — 180, итого…». Пока вы считаете, числа 250 и 180 где-то у вас в голове. Вы их удерживаете, чтобы потом использовать.
Компьютер не может удерживать что-то «в голове» просто так. Ему нужно явно сказать: «положи число 250 вот сюда и запомни, что это место называется coffee». Вот это и есть переменная.
coffee = 250 # запомнили: цена кофе
croissant = 180 # запомнили: цена круассана
total = coffee + croissant # посчитали сумму и запомнили её тоже
print(total) # напечатали результат
Ожидаемый вывод:
430
Разберём построчно:
coffee = 250— знак=тут означает не «равно», а «присвой»: возьми значение справа и дай ему имя слева. Читайте это как «пустьcoffee— это 250».croissant = 180— то же самое для второй цены.total = coffee + croissant— Python сначала вычисляет правую часть: подставляет вместоcoffeeчисло 250, вместоcroissant— 180, складывает, получает 430. И только потом даёт результату имяtotal.print(total)— печатает то, что сейчас хранится под именемtotal.
Слово # и всё после него в строке — комментарий. Python его полностью игнорирует, комментарии пишутся для людей.
Главная выгода в том, что теперь цену можно поменять в одном месте, и всё пересчитается само. Программа перестала быть жёстко зашитой.
Переменная — это не коробка, это наклейка
Почти в каждом учебнике переменную сравнивают с коробкой, в которую кладут значение. Аналогия удобная, и на первых порах она работает. Но в Python она ломается, и лучше сразу знать где.
Точнее будет так: значение лежит где-то в памяти компьютера само по себе, а имя переменной — это наклейка со стрелкой, указывающая на это значение. Одно и то же значение может иметь несколько наклеек.
age = 30
years = age # вторая наклейка на то же самое значение
print(age) # 30
print(years) # 30
age = 31 # переклеили наклейку age на другое значение
print(age) # 31
print(years) # 30 — years осталась там, где была
Ожидаемый вывод:
30
30
31
30
Почему years не стала 31? Потому что years = age не создало связь «years всегда повторяет за age». Оно один раз посмотрело, на что показывает age, и повесило туда свою наклейку. Когда age переклеили на 31, years осталась на тридцатке.
Это очень частое место, где новички ждут другого поведения. Запомните формулу: присваивание вычисляет правую часть один раз и привязывает к ней имя.
Вот тот же процесс на схеме:
Как называть переменные
Правила Python (нарушите — программа не запустится):
- имя состоит из букв, цифр и знака подчёркивания
_; - имя не может начинаться с цифры:
2price— ошибка,price2— можно; - регистр важен:
total,TotalиTOTAL— три разные переменные; - нельзя использовать служебные слова Python:
if,for,class,import,return,True,False,Noneи ещё пару десятков.
Правила хорошего тона (нарушите — программа запустится, но читать её будет тяжело):
- имя должно говорить, что внутри:
user_ageлучше, чемaилиx1; - в Python принято писать словами через подчёркивание строчными буквами:
total_price,user_name. Такой стиль называется snake_case и описан в официальном руководстве по стилю PEP 8; - не бойтесь длинных имён.
days_until_deadlineчитается лучше, чемdud.
# нормально
user_name = "Аня"
items_in_cart = 3
# запустится, но так писать не надо
x = "Аня"
q1 = 3
Типы данных: почему нельзя сложить всё со всем
У каждого значения в Python есть тип — что это вообще за штука. Тип определяет, что со значением можно делать.
Бытовая аналогия: 5 яблок и 5 килограммов — оба «пятёрки», но складывать их бессмысленно, потому что это разные сущности. Компьютер рассуждает похоже, только строже.
Пять типов, которых хватит на первое время:
Узнать тип можно функцией type():
print(type(5)) # <class 'int'>
print(type(5.0)) # <class 'float'>
print(type("5")) # <class 'str'>
print(type(True)) # <class 'bool'>
print(type(None)) # <class 'NoneType'>
Ожидаемый вывод:
<class 'int'>
<class 'float'>
<class 'str'>
<class 'bool'>
<class 'NoneType'>
Слово class тут читайте просто как «тип». К классам как к теме мы вернёмся сильно позже, в статье про объекты и классы.
Обратите внимание на разницу между 5 и "5". Первое — число, с ним можно считать. Второе — текст из одного символа, который выглядит как цифра. Для Python это разные вещи, примерно как настоящая монета и фотография монеты.
Числа: int и float
int — целые числа, float — числа с дробной частью. Разделитель дробной части — точка, не запятая.
a = 7
b = 2
print(a + b) # 9 сложение
print(a - b) # 5 вычитание
print(a * b) # 14 умножение
print(a / b) # 3.5 деление — всегда даёт float!
print(a // b) # 3 целочисленное деление: сколько раз влезло
print(a % b) # 1 остаток от деления
print(a ** b) # 49 возведение в степень
Ожидаемый вывод:
9
5
14
3.5
3
1
49
Два оператора требуют пояснения:
//— «сколько целых раз одно влезает в другое».7 // 2это 3, потому что двойка помещается в семёрку три раза (и ещё остаётся хвостик).%— тот самый хвостик, остаток.7 % 2это 1. Звучит скучно, но это рабочая лошадка: с помощью%проверяют чётность, раскладывают минуты по часам, чередуют цвета строк в таблице.
minutes = 145
hours = minutes // 60 # 2 полных часа
rest = minutes % 60 # 25 минут сверху
print(hours, rest)
Ожидаемый вывод:
2 25
Странность float, о которой лучше узнать заранее
print(0.1 + 0.2)
Ожидаемый вывод:
0.30000000000000004
Это не баг Python и не поломка вашего компьютера. Дробные числа хранятся в двоичном виде, а некоторые привычные нам десятичные дроби в двоичной системе бесконечны — примерно как 1/3 в десятичной записи бесконечна: 0.3333… Компьютер вынужден округлить, и появляется крошечная погрешность.
Что с этим делать сейчас: для вывода на экран округляйте.
result = 0.1 + 0.2
print(round(result, 2)) # 0.3 — округлить до 2 знаков после точки
И запомните правило на будущее: деньги никогда не хранят во float. Для денег есть отдельный тип Decimal — до него дойдём позже, а пока просто держите это в голове. Подробности для любопытных — в документации Python про арифметику с плавающей точкой.
Ещё одна мелочь: round(2.5) даёт 2, а не 3. Python округляет «половинки» к ближайшему чётному — это стандартное поведение, чтобы ошибки округления не накапливались в одну сторону.
Строки: текст
Строка — это текст. Записывается в кавычках, одинарных или двойных, разницы нет — главное, чтобы открывающая и закрывающая совпадали.
name = "Аня"
city = 'Казань'
Строки можно склеивать и повторять:
greeting = "Привет, " + name + "!"
print(greeting) # Привет, Аня!
print("-" * 20) # напечатает 20 дефисов подряд
Ожидаемый вывод:
Привет, Аня!
--------------------
Заметьте: + для чисел означает сложение, а для строк — склеивание. Один и тот же знак ведёт себя по-разному в зависимости от типа. Это и есть причина, по которой типы вообще существуют.
f-строки — самый удобный способ собрать текст
Склеивать через + быстро надоедает. В Python есть способ лучше: поставьте букву f перед кавычками и пишите имена переменных прямо внутри текста в фигурных скобках.
name = "Аня"
age = 30
print(f"Меня зовут {name}, мне {age} лет")
print(f"Через год будет {age + 1}") # внутри скобок можно считать
print(f"Число пи примерно {3.14159:.2f}") # :.2f — округлить до 2 знаков
Ожидаемый вывод:
Меня зовут Аня, мне 30 лет
Через год будет 31
Число пи примерно 3.14
f-строки — то, чем пользуются в реальном коде постоянно. Привыкайте к ним сразу.
Полезные действия со строками
text = " Привет, Мир "
print(text.strip()) # "Привет, Мир" — убрать пробелы по краям
print(text.strip().upper()) # "ПРИВЕТ, МИР" — в верхний регистр
print(text.strip().lower()) # "привет, мир" — в нижний регистр
print(len(text.strip())) # 11 — длина строки в символах
print("a,b,c".split(",")) # ['a', 'b', 'c'] — разрезать по запятой
Запись text.strip() читается как «попроси у объекта text выполнить действие strip». Такие действия называются методами. Точка — это «обратись к тому, что внутри».
Важно: методы строк не меняют исходную строку, а возвращают новую. text.strip() не почистил text, он вернул почищенную копию. Если результат нужен — присвойте его переменной:
text = text.strip() # вот теперь text действительно почищен
Логический тип bool
bool умеет ровно два значения: True (истина) и False (ложь). С большой буквы, это важно.
Такие значения обычно не пишут руками, а получают в результате сравнения:
age = 30
print(age > 18) # True
print(age == 30) # True
print(age != 30) # False
print(age < 10) # False
Ожидаемый вывод:
True
True
False
False
Отдельно про ==. Один знак = — это присваивание, «пусть будет». Два знака == — это вопрос «а равно ли?». Их путают буквально все на старте:
age = 30 # действие: сделать age равным 30
age == 30 # вопрос: age равен 30? -> True
Значения True и False понадобятся уже в следующей статье, когда программа начнёт принимать решения.
None — «здесь ничего нет»
None — специальное значение, означающее «значения нет». Это не ноль и не пустая строка: ноль — это конкретное количество, а None — отсутствие ответа как такового.
answer = None # пользователь ещё ничего не ответил
print(answer) # None
print(type(answer)) # <class 'NoneType'>
Аналогия: пустая тарелка (ноль порций) — это 0, а вот отсутствие тарелки вообще — это None.
Превращение одного типа в другой
Иногда данные приходят не в том виде, который нужен. Тогда их преобразуют.
print(int("42") + 1) # 43 строка "42" -> число 42
print(float("3.5") * 2) # 7.0 строка -> дробное число
print(str(42) + "5") # "425" число -> строка, потом склеили
print(int(3.99)) # 3 дробное -> целое, дробная часть ОТБРАСЫВАЕТСЯ
Ожидаемый вывод:
43
7.0
425
3
Заметьте: int(3.99) даёт 3, а не 4. Это не округление, а отсечение хвоста. Если нужно именно округлить — используйте round().
Главная ловушка новичка: input() всегда возвращает строку
Функция input() спрашивает что-то у пользователя и ждёт, пока он введёт текст с клавиатуры. Что бы человек ни ввёл — даже «5» — на выходе будет строка.
age = input("Сколько вам лет? ")
print(type(age)) # <class 'str'> — даже если ввели 30
print(age + 1) # ОШИБКА!
Ошибка будет такая:
TypeError: can only concatenate str (not "int") to str
Дословно: «Ошибка типа: к строке можно приклеить только строку, а не целое число». Python увидел + между строкой и числом и не понял, чего от него хотят — склеить текст или посчитать сумму.
Правильно так:
age = int(input("Сколько вам лет? ")) # сразу превращаем в число
print(f"Через год вам будет {age + 1}")
Если ввести 30, вывод будет:
Сколько вам лет? 30
Через год вам будет 31
Вот весь путь данных от клавиатуры до результата:
Изменение переменной на ходу
Переменную можно обновлять, в том числе на основе её же прежнего значения:
score = 0
score = score + 10 # взяли старое значение, прибавили 10, записали обратно
print(score) # 10
score += 5 # короткая запись того же самого
print(score) # 15
score -= 3 # то же для вычитания
print(score) # 12
Ожидаемый вывод:
10
15
12
Строка score = score + 10 в математике выглядела бы бессмыслицей. Но = здесь — не равенство, а команда «посчитай справа, положи налево». Сначала вычисляется score + 10 (это 10), потом результат получает имя score.
Сокращения +=, -=, *=, /= работают точно так же и просто короче.
Типичные ошибки и что означают их сообщения
Сообщения об ошибках выглядят пугающе, но они на самом деле помогают. Читайте последнюю строку — там суть.
NameError
nmae = "Аня"
print(nmae)
Всё в порядке. А вот так — нет:
name = "Аня"
print(nmae)
NameError: name 'nmae' is not defined
Дословно: «Ошибка имени: имя nmae не определено». Python не знает такой наклейки. В 90% случаев это опечатка или переменная, которую забыли создать. Проверьте написание символ за символом.
TypeError
print("5" + 5)
TypeError: can only concatenate str (not "int") to str
Дословно: «к строке можно приклеить только строку, а не int». Смешали типы. Решение: определитесь, что вам нужно — int("5") + 5 даст 10, а "5" + str(5) даст "55".
Ещё пример:
print(len(5))
TypeError: object of type 'int' has no len()
«У объекта типа int нет длины». Логично: у текста длина есть, у числа — нет.
ValueError
print(int("сорок два"))
ValueError: invalid literal for int() with base 10: 'сорок два'
Дословно: «недопустимая запись для int в десятичной системе». Тип подходящий (строка), а вот содержимое — нет: из слов число не сделать. Такое постоянно случается, когда пользователь вводит не то, что вы ожидали.
SyntaxError
name = "Аня
SyntaxError: unterminated string literal
«Незакрытая строка». Забыли вторую кавычку. Синтаксические ошибки означают, что Python вообще не смог прочитать код — программа не запустится ни на строчку.
Подробно про чтение ошибок и поиск причин — в статье Ошибки и отладка. Пока достаточно привычки: не пугаться, а читать последнюю строку.
Чек-лист «что-то не работает»
Практика
Делайте по порядку, каждое задание запускайте и смотрите на результат. Если застряли — читайте подсказку, но сначала попробуйте сами хотя бы пять минут.
1. Знакомство. Создайте переменные name (ваше имя) и city (ваш город). Выведите одной строкой: Меня зовут Аня, я из Казани.
Подсказка: понадобится f-строка. Проверьте, что кавычки открыты и закрыты.
2. Калькулятор чаевых. Заведите переменные bill = 1250 и tip_percent = 15. Посчитайте сумму чаевых и итог к оплате. Выведите оба числа, округлив до двух знаков.
Подсказка: процент от числа — это bill * tip_percent / 100. Для округления при выводе удобно {value:.2f} внутри f-строки.
3. Секунды в человеческий вид. Есть total_seconds = 3725. Выведите: 1 ч 2 мин 5 с.
Подсказка: часы — это total_seconds // 3600. Дальше нужен остаток %, и из него уже добывать минуты и секунды тем же способом.
4. Диалог с пользователем. Спросите у пользователя имя и год рождения. Выведите: Аня, в этом году вам исполнится 30. Считайте, что сейчас 2026 год.
Подсказка: input() возвращает строку. Год рождения обязательно превратите в число через int(), иначе получите TypeError. Имя преобразовывать не нужно.
5. Обмен значений. Есть a = 1 и b = 2. Сделайте так, чтобы стало a = 2, b = 1. Сначала решите задачу через третью переменную temp и объясните себе на бумаге, почему a = b первым шагом всё ломает. Потом найдите в интернете, как это делается в Python одной строкой.
Подсказка к первой части: если написать a = b, старое значение a теряется навсегда — наклейка переклеена, вернуть нечего. Поэтому его надо сначала куда-то сохранить.
Ответ на пятую задачу проверяйте так: печатайте a и b после обмена и убедитесь, что значения действительно поменялись местами.
Мини-итог
- Переменная — это имя, привязанное к значению в памяти. Не коробка, а наклейка со стрелкой.
=— это присваивание, а не равенство. Правая часть вычисляется первой, потом её результат получает имя.==— это вопрос «равны ли?», результат —TrueилиFalse.- У каждого значения есть тип:
int(целые),float(дробные),str(текст),bool(истина/ложь),None(пусто). - Тип определяет, что со значением можно делать.
5 + 5это 10,"5" + "5"это"55", а"5" + 5— ошибка. input()всегда возвращает строку. Нужно число — оберните вint()илиfloat().- Дробные числа хранятся приближённо:
0.1 + 0.2даёт0.30000000000000004. Для вывода округляйте, для денег float не используйте. - f-строки (
f"текст {переменная}") — стандартный способ собирать текст. - Ошибка — это подсказка, а не приговор. Читайте последнюю строку сообщения.
Полезное для закрепления: официальный учебник Python на русском (раздел «Использование Python как калькулятора») и PEP 8 про стиль именования.
Что дальше
Теперь программа умеет запоминать. Но она пока идёт строго сверху вниз и делает одно и то же независимо от того, что в переменных. Пора научить её выбирать: если пользователю больше 18 — одно сообщение, если меньше — другое.