Операция присваивания изменяет значение переменной, записанной слева от знака: программа вычисляет выражение справа и записывает результат в эту переменную, а прежнее значение переменной теряется. Выражение справа при этом не меняется: в x = y + 1 меняется только x, а y остается прежним.
Содержание
- Коротко о терминах
- Как выполняется присваивание: шаг за шагом
- Знак присваивания в разных языках: =, == и :=
- Присваивание как выражение и цепочки
- Присвоить — не всегда значит скопировать
- Составное присваивание: +=, -= и другие
- Обмен значений и множественное присваивание
- Типичные ошибки с присваиванием
- Выводы
- Где применяется / связь с практикой
- FAQ
Ниже — как присваивание выполняется по шагам, чем = отличается от == и :=, как работает составное присваивание (+=) и почему в Python и JavaScript «присвоить» не всегда значит «скопировать». Примеры проверены на Python 3.14, Java 25 (javac 25.0.4), Node.js 24, Free Pascal 3.2.2 и Apple clang 21 (сентябрь 2026).
Коротко о терминах
Четыре слова, которые в этой теме легко смешать:
- переменная — имя, через которое программа обращается к данным;
- значение — то, что сейчас хранится под этим именем (число, строка, ссылка на объект);
- левая часть (lvalue) — то, куда записываем: переменная, элемент массива, поле объекта;
- правая часть (rvalue) — выражение, которое вычисляется в значение.
Присваивание переменной меняет связь «имя -> значение», а объект, на который имя указывало раньше, оно не меняет — это важно для списков и объектов, об этом ниже. Исключение — присваивание элементу или полю (a[0] = 9, obj.name = "x"): здесь меняется сам контейнер, и изменение видно через все имена, которые на него ссылаются.
Как выполняется присваивание: шаг за шагом
Минимальный пример на Python:
x = 5
y = x
x = x + 1
print(x, y)
Результат:
6 5
Проследим состояние переменных после каждой строки:
| Строка | Что вычисляется справа | x | y |
|---|---|---|---|
x = 5 |
5 | 5 | нет |
y = x |
значение x, то есть 5 | 5 | 5 |
x = x + 1 |
5 + 1 = 6 | 6 | 5 |
Запись x = x + 1 с точки зрения математики абсурдна, а для программы нормальна: сначала вычисляется правая часть со старым значением x, затем результат записывается в x. Переменная y получила копию значения 5 в момент присваивания и дальше от x не зависит.
Общий порядок для простого присваивания:
- Вычислить выражение справа.
- Определить, куда писать (переменная, элемент
a[i], полеobj.name). - Записать значение; старое значение этой переменной больше недоступно через нее.
Это упрощенная модель. В каком порядке вычисляются части левой и правой стороны, если в них есть вызовы функций или индексы, зависит от языка. В Python правая часть вычисляется раньше целей слева. В C порядок вычисления операндов во многих случаях не определен стандартом, поэтому выражения вида a[i] = i++ там писать нельзя.
Знак присваивания в разных языках: =, == и :=
Главная путаница новичка — знак =. В математике это равенство, а в большинстве языков — команда «записать».
| Язык | Присваивание | Сравнение на равенство | Заметка |
|---|---|---|---|
| Pascal, школьный алгоритмический язык | := |
= |
знаки разные, путаницы нет |
| C, C++, Java, C# | = |
== |
присваивание — выражение со значением |
| Python | = (инструкция), := (выражение, с 3.8) |
== |
:= называют «моржом» |
| JavaScript | = |
=== (строгое), == (с приведением типов) |
const запрещает повторное присваивание |
| Go | =, := (объявление с присваиванием) |
== |
:= в Go и Python значит разное |
Тот же сценарий на Pascal, где знаки не путаются:
program Assign;
var
x: integer;
begin
x := 5; { присваивание }
x := x + 1;
if x = 6 then { сравнение }
writeln('x = ', x);
end.
Вывод (Free Pascal 3.2.2):
x = 6
Ошибка: = вместо == в условии
Классическая ошибка — написать присваивание там, где нужно сравнение. Разные языки реагируют по-разному, и это хорошо видно на одном и том же коде.
Неверный код на C:
#include <stdio.h>
int main(void) {
int x = 0;
if (x = 5) { /* ошибка: присваивание вместо сравнения */
printf("x = %d\n", x);
}
return 0;
}
Фактический результат: программа компилируется и печатает x = 5. Условие x = 5 записывает 5 в x, значение выражения равно 5, а любое ненулевое число в C — истина. Clang предупреждает уже без дополнительных флагов (текст Apple clang 21), GCC — только с -Wall или -Wparentheses, и формулировка у него другая:
warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
Исправление: if (x == 5). В GCC без -Wall предупреждения не будет вовсе, поэтому флаг стоит включать всегда. Если присваивание в условии нужно намеренно, его берут в дополнительные скобки: if ((x = f())) — так компилятор понимает, что это не опечатка.
В Java та же строка не компилируется, потому что условие обязано быть boolean:
Cmp.java:4: error: incompatible types: int cannot be converted to boolean
if (x = 5) {
^
Python 3.14 тоже не пропускает if x = 5: и сам подсказывает исправление:
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?
Моржовый оператор := в Python
В Python = — это инструкция, ее нельзя использовать внутри условия. Если нужно присвоить и сразу проверить значение, есть выражение присваивания :=:
data = [3, 8, 15, 2]
if (n := len(data)) > 3:
print(f"элементов: {n}")
Вывод: элементов: 4. Здесь n получает длину списка, и это же значение участвует в сравнении.
Присваивание как выражение и цепочки
В C, C++, Java и JavaScript присваивание — выражение: оно возвращает записанное значение. Поэтому работает цепочка a = b = c = 7: сначала c = 7, результат 7 идет в b, затем в a. В Pascal присваивание — только инструкция, у него нет значения.
В Python цепочка x = y = [] выглядит так же, но устроена иначе: это отдельный синтаксис, который связывает оба имени с одним и тем же объектом:
x = y = []
x.append(1)
print(y)
Вывод: [1]. Список один, имен два. Если нужны два независимых списка — пишите x = [] и y = [] отдельно.
Присвоить — не всегда значит скопировать
Для чисел пример y = x выше выглядит как копирование. Для изменяемых объектов (списки, словари, объекты классов) в Python присваивание копирует ссылку, а не данные:
a = [1, 2]
b = a # второе имя для того же списка
b.append(3) # изменение объекта, а не переменной
print(a, b, a is b)
b = [9] # присваивание: b теперь связана с новым списком
print(a, b, a is b)
Вывод:
[1, 2, 3] [1, 2, 3] True
[1, 2, 3] [9] False
Здесь видны два разных действия. b.append(3) меняет сам список, и изменение видно через оба имени. b = [9] — это присваивание: меняется только то, на что указывает b, а список под именем a остается прежним. Если нужна независимая копия, используют b = a.copy() или b = list(a) (для вложенных структур — copy.deepcopy).
В JavaScript то же разделение закреплено в const: оно запрещает повторное присваивание переменной, но не изменение объекта.
const nums = [1, 2];
nums.push(3); // изменение массива разрешено
console.log(nums); // [ 1, 2, 3 ]
nums = []; // повторное присваивание запрещено
Последняя строка в Node.js 24 падает с ошибкой TypeError: Assignment to constant variable.
Составное присваивание: +=, -= и другие
Составной оператор объединяет арифметическую или побитовую операцию с записью результата: x += 3 читается как «увеличить x на 3».
| Оператор | Пример | Смысл для чисел |
|---|---|---|
+= |
x += 3 |
x = x + 3 |
-= |
x -= 3 |
x = x — 3 |
*= |
x *= 2 |
x = x * 2 |
/= |
x /= 2 |
x = x / 2 (в Python результат — float) |
//= |
x //= 2 |
целочисленное деление, только Python |
%= |
x %= 3 |
остаток от деления |
**= |
x **= 2 |
возведение в степень (Python, JavaScript) |
&=, |=, ^=, <<=, >>= |
x <<= 1 |
побитовые операции и сдвиги |
Формула «x += 3 это x = x + 3» — упрощение. Есть два важных отличия.
Первое: левая часть вычисляется один раз. В a[f()] += 1 функция f() вызывается один раз, а в a[f()] = a[f()] + 1 — дважды.
Второе: для изменяемых объектов Python += может менять объект на месте, а x = x + ... создает новый:
a = [1, 2]
alias = a
a += [3] # для списка: изменение на месте
print(alias, a is alias)
a = [1, 2]
alias = a
a = a + [3] # новый список, alias смотрит на старый
print(alias, a is alias)
s = "ab"
t = s
s += "c" # строка неизменяема: создается новая
print(t, s)
Вывод:
[1, 2, 3] True
[1, 2] False
ab abc
В Java у составного присваивания есть еще одна особенность — неявное приведение типа к типу левой части:
public class Main {
public static void main(String[] args) {
byte b = 10;
b += 5; // неявное приведение к byte
System.out.println(b);
}
}
Программа печатает 15. А строка b = b + 5; не компилируется: b + 5 имеет тип int, и javac 25 сообщает error: incompatible types: possible lossy conversion from int to byte. У этого удобства есть цена: при += переполнение byte пройдет молча.
Обмен значений и множественное присваивание
Чтобы поменять значения двух переменных, в C и Java нужна временная переменная: tmp = a; a = b; b = tmp;. В Python и JavaScript есть множественное присваивание:
a, b = 1, 2
a, b = b, a
print(a, b) # 2 1
В JavaScript то же делается деструктуризацией: [a, b] = [b, a];. В Python правая часть b, a сначала полностью вычисляется в кортеж, и только потом значения раскладываются по именам слева — поэтому старое значение a не теряется.
Встречаются и трюки обмена без временной переменной через сложение (a = a + b; b = a - b; a = a - b) или XOR. Они работают только для чисел, сложение может переполниться в языках с фиксированной разрядностью, а XOR-вариант обнуляет значение, если обе стороны — одна и та же ячейка памяти. В рабочем коде лучше временная переменная или множественное присваивание.
Типичные ошибки с присваиванием
| Симптом | Причина | Что сделать |
|---|---|---|
| Условие в C всегда истинно, переменная «сама» меняется | = вместо == в if |
писать ==, компилировать с -Wall |
NameError в Python / ошибка компиляции «might not have been initialized» в Java |
переменной не присвоили значение до чтения | присвоить начальное значение до первого использования |
| Изменили копию списка, а поменялся оригинал | b = a копирует ссылку |
a.copy(), list(a) или copy.deepcopy |
| Два «разных» списка ведут себя как один | x = y = [] |
создать списки отдельными присваиваниями |
TypeError: Assignment to constant variable. |
повторное присваивание const |
использовать let или менять содержимое объекта |
Выводы
- Операция присваивания изменяет значение переменной слева от знака; правая часть сначала вычисляется, затем результат записывается, старое значение теряется.
=в C, Java, Python и JavaScript — присваивание, сравнение —==(в JavaScript обычно===); в Pascal присваивание —:=, сравнение —=.- В C присваивание — выражение со значением, поэтому
if (x = 5)компилируется и работает неправильно; Java и Python такой код не пропускают. - Составное присваивание (
+=и др.) вычисляет левую часть один раз; в Python для списков оно меняет объект на месте, в Java — неявно приводит тип. - Для списков и объектов присваивание копирует ссылку, а не данные: изменение объекта и повторное присваивание — разные действия.
Где применяется / связь с практикой
Освойте тему на практике
Присваивание встречается почти в каждой строке программы, и ошибки с ним — одни из самых частых у начинающих: перепутанные = и ==, неожиданно общий список, «потерянное» значение при обмене. Разница между изменением объекта и повторным присваиванием в Python дальше всплывает в функциях, аргументах по умолчанию и работе с коллекциями. Если хочется разобрать переменные, типы и изменяемость данных на задачах с проверкой, посмотрите курс «Python-разработчик. Базовый уровень». Разобрать отдельные темы с преподавателями можно на открытых уроках Otus.
FAQ
Можно ли присвоить значение выражению, например x + 1 = 5?
Нет. Слева должно стоять место для записи: переменная, элемент массива или поле объекта. Python на такую строку выдает SyntaxError, C и Java — ошибку компиляции.
Чем присваивание отличается от инициализации?
Инициализация задает значение при объявлении переменной (int x = 5;), присваивание меняет значение уже существующей переменной. В C++ это разные операции: для объектов классов при инициализации вызывается конструктор, а при присваивании — оператор присваивания.
Почему в школьной информатике пишут :=, а в Python =?
Школьный алгоритмический язык и Pascal используют :=, чтобы не путать присваивание с математическим равенством. C и выросшие из него языки выбрали короткий = для присваивания и == для сравнения; Python взял ту же пару.



