Программирование с нуля Переменные и типы данных: как программа хранит информацию
0%

Переменные и типы данных: как программа хранит информацию

Переменные и типы данных: как программа хранит информацию

В прошлой статье вы запустили первую программу и увидели, как компьютер печатает текст на экран. Это уже настоящая программа, но пока она делает ровно одно и то же при каждом запуске. Чтобы программа стала полезной, ей нужно запоминать — имя пользователя, сумму в корзине, счёт в игре, ответ на вопрос. Всё, что программа помнит во время работы, живёт в переменных.

Эта статья — про то, что такое переменная, чем «строка» отличается от «числа» и почему компьютер иногда отказывается складывать две вещи, которые вам кажутся совершенно складываемыми.

Если что-то не получится с первого раза — это нормально. Здесь буквально всё разбирается по шагам, и каждый пример можно набрать руками и запустить.

Зачем вообще что-то хранить

Представьте, что вы считаете стоимость заказа. Вы говорите вслух: «Так, кофе — 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 — одно сообщение, если меньше — другое.

Условия: как программа принимает решения

Нашли неточность? Выделите фрагмент текста — рядом появится жучок.

Нужен разбор именно вашей ситуации?

Статья описывает общий случай. Если у вас частный — можно разобрать его отдельно, платно. А если не хватает целого материала, предложите тему: её оплачивают вскладчину, и она выходит открытой для всех.

Доска запросов