Переменные в программировании: что это, типы данных и область видимости

Переменные в программировании: что это, типы данных и область видимости Полезное

Переменная в программировании — это именованное хранилище данных: у нее есть имя, по которому программа к ней обращается, текущее значение и тип, который определяет, какие значения допустимы и какие операции с ними можно выполнять. В Java и C тип закреплен за самой переменной, в Python и JavaScript — за ее текущим значением. Значение переменной можно прочитать и, если это не константа, заменить другим.

Ниже разберем, как объявить переменную в Python, JavaScript, Java и C, чем статическая типизация отличается от динамической, что такое константы, область видимости и время жизни, как называть переменные и какие ошибки встречаются чаще всего. Примеры проверены на Python 3.14, Node.js 24, Java 25 и компиляторе Clang (сентябрь 2026).

Данные, значение, тип и переменная: мини-словарь

Эти слова часто смешивают, поэтому сначала разведем их:

Термин Что это Пример
Данные Любая информация, с которой работает программа возраст пользователя, текст письма
Значение Конкретный кусок данных в конкретный момент 17, "Анна"
Тип Множество допустимых значений и операций над ними int, str, boolean
Литерал Значение, записанное прямо в коде 17 в строке age = 17
Переменная Имя, связанное со значением, которое можно менять age
Константа Имя, значение которого после задания не меняют PI

Аналогия-якорь: переменная похожа на подписанную коробку. Надпись — имя, содержимое — значение, форма коробки — тип (в круглую коробку не положить квадратный предмет).

Это упрощение. В C и Java для примитивных типов имя действительно обозначает участок памяти фиксированного размера. В Python и JavaScript точнее говорить, что имя ссылается на объект, а тип хранится у объекта, а не у имени. Для первых шагов модель коробки работает, но разница всплывет в разделе о типизации.

Минимальный пример на Python

name = "Анна"        # строка (str)
age = 17             # целое число (int)
height = 1.68        # дробное число (float)
is_student = True    # логическое значение (bool)

print(name, age, height, is_student)
print(type(age).__name__, type(height).__name__)

age = age + 1        # то же имя, новое значение
print(age)

Результат запуска:

Анна 17 1.68 True
int float
18

Что здесь произошло. Четыре строки создали четыре переменные и сразу дали им значения. Python не требует писать тип: он определяется по значению (17 — int, 1.68 — float). Функция type() показывает тип текущего значения. Последняя строка прочитала старое значение age, прибавила единицу и связала имя с новым значением 18.

Объявление переменной в разных языках

Во многих языках различают три действия. Объявление сообщает, что имя существует. Инициализация — первое значение. Дальнейшая замена значения — присваивание (подробно о нем — отдельная тема). Часто объявление и инициализацию пишут одной строкой.

Язык Переменная Константа Нужно ли писать тип
Python count = 3 MAX_USERS = 100 (соглашение) нет
JavaScript let count = 3; const PI = 3.14159; нет
Java int count = 3; или var count = 3; final double PI = 3.14159; да, либо вывод через var (с Java 10)
C int count = 3; const double PI = 3.14159; да

Тот же пример на Java:

public class Main {
    public static void main(String[] args) {
        int count = 3;                 // тип указан явно
        final double PI = 3.14159;     // константа
        var title = "Переменные";      // тип String выведен компилятором
        count = count + 1;
        System.out.println(count + " " + PI + " " + title);
    }
}

В консоли появится 4 3.14159 Переменные. Обратите внимание: var в Java не делает переменную «бестиповой». Компилятор сам выводит тип String по значению, и дальше положить туда число уже нельзя.

На C объявление выглядит так же явно:

#include <stdio.h>

int main(void) {
    int count = 3;                /* тип указан явно */
    const double PI = 3.14159;    /* изменить нельзя */
    count = count + 1;
    printf("%d %.5f\n", count, PI);
    return 0;
}

Вывод: 4 3.14159. Особенности переменных в C (размеры типов, указатели, классы памяти) разобраны в статье переменные в языке C.

В JavaScript для новых программ используют let и const. Старое var работает, но у него другая область видимости — об этом ниже.

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

Статическая типизация — тип переменной известен до запуска и проверяется компилятором (Java, C, C#, Go). Динамическая — тип проверяется во время выполнения, а одно и то же имя может сначала указывать на число, потом на строку (Python, JavaScript, PHP).

Неверный код на Java — попытка положить строку в int:

int x = 5;
x = "пять";

Фактический результат (javac, JDK 25) — программа не компилируется:

Bad1.java:4: error: incompatible types: String cannot be converted to int
        x = "пять";
            ^

В Python то же самое допустимо: сначала x = 5 (тип int), затем x = "пять" (тип str), ошибки нет. Но это не значит, что Python не следит за типами. Попытка сложить строку и число падает во время выполнения:

print("Возраст: " + 17)
TypeError: can only concatenate str (not "int") to str

Исправление — явно преобразовать число: "Возраст: " + str(17) или f-строка f"Возраст: {17}".

JavaScript в той же ситуации ошибку не выдаст, а неявно преобразует тип:

console.log("Возраст: " + 17);  // Возраст: 17
console.log("5" - 2);           // 3

Отсюда вторая ось — сильная и слабая типизация: насколько охотно язык сам преобразует типы. Python строже JavaScript, хотя оба динамические. Строгих формальных определений у «сильной» и «слабой» типизации нет, это скорее шкала, чем два класса.

Язык Когда проверяется тип Неявные преобразования
Java, C# при компиляции мало (расширение чисел)
C при компиляции много числовых преобразований
Python при выполнении мало, "a" + 1 — ошибка
JavaScript при выполнении много, "5" - 2 дает 3

Если нужны проверки типов до запуска в Python или JavaScript, используют аннотации с внешним анализатором (mypy для Python) или TypeScript.

Константы

Константа — имя, значение которого после задания менять не собираются. Языки обеспечивают это по-разному.

JavaScript const запрещает переприсваивание:

const PI = 3.14159;
PI = 3;
TypeError: Assignment to constant variable.

Важная граница: const защищает связь имени со значением, а не содержимое объекта. Код const user = { name: "Анна" }; user.name = "Олег"; отработает без ошибки.

В Java final проверяется компилятором (error: cannot assign a value to final variable PI), в C const — тоже на этапе компиляции. В Python настоящих констант нет: имя в верхнем регистре MAX_USERS = 100 — только соглашение, повторное MAX_USERS = 5 выполнится молча. Аннотация typing.Final ловит такое переприсваивание, но только при проверке внешним анализатором, сам интерпретатор ее не соблюдает.

Область видимости и время жизни

Область видимости — часть кода, где имя доступно. Время жизни — промежуток выполнения, в течение которого переменная существует. Это разные вещи: переменная может существовать, но быть невидимой из текущего места.

Грубо переменные делят на глобальные (объявлены на уровне модуля или файла, видны во многих местах) и локальные (объявлены внутри функции или блока, видны только там). Локальная переменная функции создается заново при каждом вызове:

def visit():
    count = 0
    count += 1
    return count

print(visit(), visit())

Вывод 1 1: после выхода из функции count пропадает, второй вызов начинает с нуля.

В JavaScript есть разница между var и let. var видна во всей функции, let и const — только внутри блока { }:

if (true) {
  var a = 1;
  let b = 2;
}
console.log(a);  // 1
console.log(b);  // ReferenceError: b is not defined

Переменные let и const еще и нельзя читать до строки объявления: console.log(total); let total = 10; дает ReferenceError: Cannot access 'total' before initialization.

Типичная ловушка Python — изменить глобальную переменную внутри функции.

Неверный код:

counter = 0

def add_click():
    counter += 1

add_click()

Результат:

UnboundLocalError: cannot access local variable 'counter' where it is not associated with a value

Присваивание внутри функции делает counter локальным именем, а прочитать его до первого значения нельзя. Исправление без глобального состояния — передать значение и вернуть результат:

def add_click(counter):
    return counter + 1

counter = 0
counter = add_click(counter)
counter = add_click(counter)
print(counter)  # 2

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

Как называть переменные

Правила, общие для Python, JavaScript, Java и C:

  • имя состоит из букв, цифр и _ (в JavaScript и Java допустим еще $), не начинается с цифры, без пробелов;
  • ключевые слова языка (class, for, if, return) использовать нельзя; список у каждого языка свой: int — ключевое слово в Java и C, но в Python это имя встроенного типа, и int = 5 там выполнится (с последствиями, как у list ниже);
  • регистр важен: age и Age — разные переменные;
  • в Java, C и для let/const в JavaScript нельзя дважды объявить одно имя в одной области видимости; в Python отдельного объявления нет, повторное x = ... просто заменяет значение.

Соглашения по стилю отличаются: в Python принят snake_case (user_name, по PEP 8), в JavaScript и Java — camelCase (userName), константы пишут UPPER_CASE. Имя должно объяснять смысл: days_left лучше, чем d или x1. Кириллица в именах Python, Java и JavaScript формально допустима, но в командной разработке ее не используют.

Частые ошибки с переменными

Опечатка в имени. user_name = "Анна", затем print(user_nmae) — Python 3.14 сообщает NameError: name 'user_nmae' is not defined. Did you mean: 'user_name'?. Подсказку «Did you mean» стоит читать — чаще всего она права.

Чтение до инициализации. В Java int total; System.out.println(total); не компилируется: error: variable total might not have been initialized. В C локальная переменная без начального значения содержит непредсказуемый мусор, и компилятор не обязан об этом предупреждать — всегда задавайте начальное значение.

Перекрытие встроенного имени. Переменная list = [3, 1, 2] в Python прячет встроенную функцию list, и следующий вызов list("abc") падает с TypeError: 'list' object is not callable. Исправление — другое имя: numbers, items.

Переполнение числа фиксированного размера. В Java int занимает 32 бита, и Integer.MAX_VALUE + 1 дает -2147483648 без всякой ошибки. Если значение может быть больше примерно 2,1 млрд, нужен long. В Python целые числа неограниченной длины, этой проблемы там нет.

Сравнение дробных чисел. 0.1 + 0.2 в Python дает 0.30000000000000004, а 0.1 + 0.2 == 0.3 — False. Типы float/double хранят двоичное приближение (стандарт IEEE 754), поэтому деньги считают в целых копейках или типом Decimal, а дроби сравнивают с допуском (math.isclose).

Выводы

  • Переменная — именованное хранилище данных: имя, значение и тип; значение можно читать и заменять.
  • В статически типизированных языках (Java, C) тип фиксируется при объявлении и проверяется компилятором; в динамических (Python, JavaScript) тип принадлежит значению и проверяется при выполнении.
  • Константы защищены по-разному: const в JS и final в Java запрещают переприсваивание, в Python это только соглашение об именовании.
  • Область видимости отвечает на вопрос «где имя доступно», время жизни — «когда переменная существует»; локальные переменные функции создаются заново при каждом вызове.
  • Большинство ошибок новичка — опечатки в именах, чтение до инициализации, перекрытие встроенных имен и неверные ожидания от типа.

Где применяется / связь с практикой

Освойте тему на практике

Переменные — первая тема любого курса программирования, и от того, насколько точно вы понимаете типы и области видимости, зависит, как быстро пойдут функции, коллекции и классы. Если хотите пройти основы последовательно, с практическими заданиями и проверкой кода, посмотрите программу курса «Python-разработчик. Базовый уровень». Разобраться в формате обучения можно на бесплатных открытых уроках Otus.

FAQ

Чем переменная отличается от ячейки памяти?
Ячейка памяти — физический адрес, переменная — абстракция языка с именем и типом. Компилятор может держать переменную в регистре процессора или вовсе убрать ее при оптимизации.

Можно ли объявить переменную без значения?
В Java и C — да (int total;), но читать ее до присваивания нельзя или опасно. В Python отдельного объявления нет: имя появляется в момент первого присваивания, а для «пустого» значения используют None.

Сколько памяти занимает переменная?
Зависит от языка и типа: int в Java — всегда 4 байта, в C размер int определяет платформа (обычно 4 байта), а в Python даже маленькое целое — объект с заголовком, заметно больше 4 байт.

OTUS Журнал
Скидка 5% 12-19 октября на курсы (popup)
Бесплатные открытые уроки (поп-ап)