Операторы в Python от А до Я: что значит каждый символ

Операторы в Python от А до Я: что значит каждый символ Полезное

Оператор в Python — это символ или ключевое слово, которое выполняет действие над значениями (операндами) и возвращает новое значение. Коротко о самых частых вопросах «что значит в питоне»: // — деление с округлением вниз, % — остаток от деления, ** — возведение в степень, == — равенство значений, is — тот же самый объект в памяти, in — «содержится в», and/or — логика с коротким замыканием, := — присваивание прямо внутри выражения.

Статья устроена как справочник: найдите символ в таблице, а ниже — точное поведение, граничные случаи и типичные ошибки. Все примеры и выводы проверены на Python 3.14.7 в сентябре 2026 года.

Три термина, которые дальше не смешиваю:

  • выражение — то, что вычисляется в значение (a + 1, x > 3);
  • оператор — символ внутри выражения (+, >, in);
  • инструкция — команда, которая ничего не возвращает (x = 5, if, for). Поэтому обычное = в Python — часть инструкции, а не оператор выражения, в отличие от :=.

Шпаргалка: что значит каждый символ

Символ Что значит Пример Результат
+ - * сложение, вычитание, умножение 7 * 2 14
/ деление, для int и float дает float 7 / 2 3.5
// деление с округлением вниз 7 // 2 3
% остаток от деления 7 % 2 1
** степень 2 ** 10 1024
== != равно, не равно 3 != 4 True
< > <= >= сравнение, можно цепочкой 1 < 5 < 10 True
is is not тот же объект или нет x is None True/False
in not in содержится ли элемент "th" in "python" True
and or not логические И, ИЛИ, НЕ "" or "def" 'def'
& | ^ ~ побитовые И, ИЛИ, XOR, НЕ 5 ^ 2 7
<< >> сдвиг битов 1 << 4 16
+= -= //= и т.д. изменить и присвоить x += 1 x больше на 1
:= присвоить внутри выражения (n := 3) > 2 True, n = 3
@ матричное умножение (numpy и др.) A @ B произведение матриц

Минимальный пример: все группы сразу

a, b = 17, 5

print(a / b)     # обычное деление
print(a // b)    # целочисленное деление вниз
print(a % b)     # остаток
print(a ** 2)    # степень
print(a == 17, a != b)
print(3 in [1, 2, 3], "py" in "python")
print(a > 10 and b > 10, a > 10 or b > 10, not a)

if (n := len("otus")) > 3:
    print("длина", n)

Вывод:

3.4
3
2
289
True True
True True
False True False
длина 4

Обратите внимание на not a: число 17 «истинно», поэтому not 17 дает False. Дальше разбираю каждую группу там, где у нее есть подвох.

Арифметика: /, //, % и **

/ в Python 3 для целых и дробных чисел возвращает float, даже если делится нацело: 10 / 5 дает 2.0 (у Fraction, Decimal и complex результат своего типа). Если нужно целое, берут //.

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

print(7 // 2, 7 % 2)
print(-7 // 2, -7 % 2)
print(7 // -2, 7 % -2)

a, b = -7, 2
print(a == (a // b) * b + a % b)
print(divmod(-7, 2))
print(7.5 // 2, 7.5 % 2)
3 1
-4 1
-4 -1
True
(-4, 1)
3.0 1.5

Правило, которое связывает // и %: a == (a // b) * b + a % b, а знак остатка совпадает со знаком делителя. В C и Java -7 / 2 дает -3, а остаток -1, поэтому код, перенесенный из этих языков, на отрицательных числах в Python дает другой ответ. divmod(a, b) возвращает оба числа сразу. С float оба оператора тоже работают и возвращают float.

** — степень, и у нее две особенности приоритета:

print(2 ** 3 ** 2, (2 ** 3) ** 2)
print(-2 ** 2, (-2) ** 2)
print(2 ** -1)
512 64
-4 4
0.5

Степень считается справа налево (2 ** 9), а унарный минус слева слабее степени: -2 ** 2 читается как -(2 ** 2). Справа от ** минус работает как обычно: 2 ** -1 равно 0.5.

Деление на ноль — ошибка, а не бесконечность:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero

Один и тот же символ значит разное для разных типов: "abc" * 2 дает 'abcabc', [0] * 3 дает [0, 0, 0], а + для строк склеивает их. Смысл оператора определяют типы операндов: сначала пробуется метод левого (__add__), а если он не умеет работать с правым — отраженный метод правого (__radd__).

Сравнение: ==, != и цепочки

== сравнивает значения, != — «не равно» (в Python 3 он есть; удален был старый вариант <> из Python 2). Сравнения можно писать цепочкой, как в математике: 1 < x < 10 означает 1 < x and x < 10.

Две ловушки. Дробные числа хранятся в двоичном виде приближенно, поэтому 0.1 + 0.2 == 0.3 дает False; для float сравнивают через math.isclose(0.1 + 0.2, 0.3) — это True. А несравнимые типы вызывают ошибку, а не False:

TypeError: '<' not supported between instances of 'int' and 'str'

is против ==: объект или значение

is проверяет, что две переменные указывают на один и тот же объект, а == — что значения равны.

a = [1, 2]
b = [1, 2]
c = a
print(a == b, a is b, a is c)
True False True

Списки a и b равны по содержимому, но это два разных объекта. c — второе имя того же списка. Практическое правило: is используют для None (if x is None) и других объектов-одиночек, все остальное сравнивают через ==.

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

<stdin>:2: SyntaxWarning: "is" with 'int' literal. Did you mean "=="?

in и not in: что именно ищется

in отвечает на вопрос «есть ли элемент внутри». Что считается элементом, зависит от типа:

d = {"python": 3, "java": 25}
print("python" in d, 3 in d, 3 in d.values())
print("th" in "python", [1, 2] in [1, 2, 3], 5 not in {1, 2})
True False True
True False True

Для словаря in ищет среди ключей, не значений. Для строки — подстроку. Для списка — элемент целиком, поэтому [1, 2] in [1, 2, 3] дает False: такого элемента-списка там нет. Скорость тоже разная: в списке поиск перебором, в set и dict в среднем за постоянное время — при частых проверках большие коллекции лучше держать множеством.

and, or, not: возвращают операнд, а не True/False

and и or вычисляют правую часть, только если без нее ответ неясен (короткое замыкание), и возвращают один из операндов:

print("" or "по умолчанию", 0 and 1 / 0, [] or None)
по умолчанию 0 None

Пустая строка «ложна», поэтому or вернул правую часть — так задают значения по умолчанию. В 0 and 1 / 0 деление даже не выполнялось: левая часть уже ложна. not всегда возвращает True или False.

Самая частая логическая ошибка новичка:

color = "синий"
print(color == "красный" or "зеленый")    # неверно
print(color in ("красный", "зеленый"))    # верно
зеленый
False

Первая строка читается как (color == "красный") or "зеленый": левая часть False, и or вернул непустую строку, которая в if считается истинной. Условие срабатывает всегда. Исправление — in с кортежем вариантов.

Побитовые операторы: & | ^ ~ << >>

Работают с двоичным представлением целых чисел: 5 & 3 дает 1, 5 | 3 дает 7, ~5 дает -6 (для целых ~x == -x - 1), 1 << 4 дает 16, 256 >> 2 дает 64.

Главная путаница — ^. Это не степень, а исключающее ИЛИ: 10 ^ 2 дает 8, а 10 ** 2 дает 100. И & не заменяет and: and работает с истинностью и замыкается, & вычисляет обе части и работает с битами.

Присваивание: +=, изменяемые объекты и :=

x += 1 — сокращение для x = x + 1, но для изменяемых объектов есть разница. Для списка += меняет сам объект, а s = s + [...] создает новый:

s = [1]
t = s
s += [2]
print(s, t)
s = s + [3]
print(s, t)
[1, 2] [1, 2]
[1, 2, 3] [1, 2]

После += изменился и t — это то же самое имя для того же списка. Для чисел и строк разницы нет: они неизменяемые. Инкремента x++ в Python нет — это SyntaxError: invalid syntax, а ++x молча дает просто x (два унарных плюса).

:= (появился в Python 3.8, в обиходе «моржовый оператор») присваивает и сразу возвращает значение. У него самый низкий приоритет, поэтому без скобок легко получить не то:

data = [4, 8, 15]
if n := len(data) > 2:
    print("n =", n)
if (n := len(data)) > 2:
    print("n =", n)
n = True
n = 3

В первом if в n попал результат сравнения. Скобки вокруг n := ... ставьте всегда.

Приоритет операторов

Сверху — то, что выполняется раньше. Операторы одной строки выполняются слева направо, кроме ** (справа налево) и сравнений: они образуют цепочку, a < b < c значит a < b and b < c, а не (a < b) < c.

Приоритет Операторы
1 (высший) (), вызов, индекс x[i]
2 **
3 унарные +x, -x, ~x
4 *, @, /, //, %
5 +, -
6 <<, >>
7 &
8 ^
9 |
10 сравнения, in, not in, is, is not
11 not
12 and
13 or
14 x if условие else y
15 lambda
16 (низший) :=

Отсюда not 1 == 2 дает True (сначала сравнение), а True or False and False дает True, потому что and сильнее or; со скобками (True or False) and False будет False. Если сомневаетесь в порядке — ставьте скобки: читателю кода это тоже помогает.

Символы, которые похожи на операторы, но ими не являются

Запись Что значит
def f(x) -> int: аннотация типа результата, не оператор
*args, **kwargs сбор и распаковка аргументов, не умножение
@decorator над функцией декоратор; @ между значениями — матричное умножение
a[1:3] срез, двоеточие не оператор
x = 5 инструкция присваивания

Выводы

  • // округляет вниз, % берет знак делителя, и они связаны правилом a == (a // b) * b + a % b — на отрицательных числах Python расходится с C и Java.
  • == сравнивает значения, is — идентичность объектов; is нужен для None, а не для чисел и строк.
  • in ищет ключи в словаре, подстроку в строке и целый элемент в списке.
  • and/or возвращают операнд и замыкаются; условие x == 1 or 2 истинно всегда, правильно x in (1, 2).
  • ^ — XOR, а не степень; := имеет самый низкий приоритет и требует скобок.

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

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

Операторы — первое, на чем спотыкаются при чтении чужого кода: цикл по страницам через // и %, проверка if user is None, значения по умолчанию через or, фильтры с in. Если хотите разобрать синтаксис Python последовательно, с задачами и ревью кода, посмотрите курс «Python-разработчик. Базовый уровень». Живые разборы отдельных тем проходят на открытых уроках Otus.

Смежные темы: операторы Python по группам, операторы Python: арифметика, сравнение, is и in.

FAQ

Есть ли в Python тернарный оператор?
Да, в виде выражения значение1 if условие else значение2, например "четное" if n % 2 == 0 else "нечетное". Записи ?: из C в Python нет.

Можно ли изменить поведение оператора для своего класса?
Да, через специальные методы: __add__ для +, __eq__ для ==, __contains__ для in. Именно так + склеивает строки, а @ в numpy умножает матрицы. Переопределить is, and, or и not так нельзя.

Чем divmod(a, b) лучше пары a // b и a % b?
Результат тот же, но одним вызовом и кортежем (частное, остаток): удобно при переводе секунд в минуты и секунды или номера элемента в строку и столбец.

OTUS Журнал
Скидка 5% 14-20 сентября на курсы (popup)