Операторы

Мы уже подробно рассматрели операторы для большинства типов в предыдущих лекциях. Но давайте еще раз сделаем обзор и подведем итоги.

Если взять выражение a + b, то a и b будут правым и левым операндом. А знак + это оператор и в зависимости от того какого типа операнды он будет называться по разному или вообще может выдавать ошибку если такая операция не возможна. Например для чисел + — это оператор сложения, а для строк конкатенации, хотя проще говорить "склеивание". А вот числа и строки складывать нельзя:

>>> a = "Добро пожаловать в "
>>> b = 3001
>>> a + b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str

Если вы сталкивались с другими языками программирования, то там такая операция может быть допустима.

Еще пример с оператором *, он в зависимости от контекста будет либо умножением, либо оператором повторения:

>>> 3.14 * 2
6.28
>>> "булка " * 3
'булка булка булка '

На самом деле звездочка это исключение из правил и единственный арифметический оператор который имеет смысл для работы со строками и числами одновременно. Но так же можно использовать логические операторы чтобы проверять на истинность строки и числа. Давайте пройдемся по всем операторам еще раз полность.

Виды операторов

В Python есть много видов операторов, часть мы уже рассматривали в соответствующих темах. Вот полный список:

  • Арифметические операторы
  • Операторы сравнения (реляционные)
  • Операторы присваивания
  • Логические операторы
  • Операторы членства
  • Операторы тождественности
  • Побитовые операторы

Теперь рассмотрим все операторы подробно.

Арифметические операторы

Операция Название и значение Пример
x + y Сумма x и y 2+24
x - y Разница x и y 3-21
x * y Произведение x и y 2*36
x / y Деление x и y 5/22.5
x // y Целочисленное деление 7//32
x % y Остаток от деления 8%32
x ** y x в степени y 2**101024

Операторы сравнения (реляционные)

Операция Название и значение Пример
x == y Равенство, равны ли оба операнда 2 == 2True
x != y Не равенство, не равны ли оба оператора 3 != 2True
x > y Больше x чем y 2>3False
x < y Меньше меньше ли x чем y 2<5True
x <= y Меньше или равно x чеи y 4>=3True
x >= y Больше или равно x чем y 2>=4False

Раньше существовал оператор <>, но его убрали из языка, вместо него используется !=.

Операторы присваивания

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

>>> a = 1
>>> a
1
>>> a += 5
>>> a
6

Оператор += сложения с присваиванием взял старое значение переменной a и добавил к ней число и присвоил переменной a новое значение. Любой оператор присваивания можно переписать в арифметической форме:

>>> a = 1
>>> a = a + 5
>>> a
6

В таблице представлены все операторы присваивания, для удобства примеры даны с допущением, что до выполнения операции каждий раз переменной x было присвоено значение 10:

Операция Название и значение Пример (начальный x = 10)
x = y Присваиване нового значения x = 22
x += y Сложение с присваиванием x += 212
x -= y Вычитание с присваиванием x -= 28
x *= y Умножение с присваиванием x *= 220
x /= y Деление с присваиванием x /= 25.0
x %= y Остаток от деления с присваиванием x %= 50
x **= y Возведение в степень с присваиванием x **= 31000
x //= y Целочисленное деление с присваиванием x //= 25

Логические операторы

Оператор Название и значение Пример
and Логическое И, проверка на истинность обоих операндов True and TrueTrue,
True and FalseFalse
or Логическое ИЛИ, проверка на хотя бы одного операнда True or FalseTrue
not Логическое НЕ, изменяет логическое значение оператора на противоположное not TrueFalse

В Python существует ленивая проверка операций. Если при проверке оператора or левая часть оператора окажется истинной, то проверки правой уже не будет. Например, нельзя делить на ноль:

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

Но если спрятать деление на ноль в правую часть, то вычисления не произойдет:

>>> True or 10/0
True

Иногда это приводит к ошибкам которые сложно отладить, потому что приходится подобрать такие условия, чтобы левая часть была ложной и тогда вычисления дойдут и до второго операнда:

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

Операторы членства

Множества будут подробно рассмотрены в следующей части курса. Операторы членства позволяют определить входит ли какой-то элемент в список, строку или множество другого типа.

Операция Название и значение Пример
x in y Проверка на вхождение в множество 'cat' in 'catastrophe'True
x not in y Проверка на не вхождение в множество 1 not in [1, 2, 3, 4]False

Оператор проверки на вхождение множества имеет одинаковый синтаксис вне зависимости от того какое множество используется:

>>> pets=['dog', 'cat', 'ferret']
>>> 'fox' in pets
False
>>> 'fox' not in pets
True

Если делать проверку по словарю, то проверяется есть ли элемент в списке ключей:

>>> money = {'USD': 'US Dollar', 'EUR': 'Euro', 'SGD': 'Singapore Dollar'}
>>> 'USD' in money
True
>>> 'BTC' in money
False

Операторы тождественности

Позволяют проверить указывают ли переменные на один и тот же объект в памяти

Операция Название и значение Пример
x is y Проверка указывают ли оба объекта на тот же объект в памяти True если id(x) равен id(y)
x is not y Проверка на то что переменные указывают на разные объекты False если id(x) равен id(y)

Оператор тождественности похож на ==, но их работа все же отличается. Если погрузиться в особенности внутреннего устройства работы с памятью, то можно встретить некоторые непредсказуемые моменты. Например, вот этот пример кажется не совсем логичным:

>>> a = 'Шум и гам в этом логове жутком'
>>> c = 'Шум и гам в этом логове жутком'
>>> a == c
True
>>> a is c
False

Дело в том, что когда Python создает новую переменную, то выделяет для нее новую область памяти и делает на нее ссылку которую связывает с идентификатором. И в памяти могут храниться два одинаковых объекта. Если же сделать ссылку на старую область памяти, то объекты станут тождественны:

>>> b = a
>>> a is b
True
>>> a == b
True

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

Для работы с битами есть специальный набор операторов. Они очень похожи на логические операторы которые проверяют True и False, но используют вместо них 1 и 0. Когда сравнивается два операнда, то они сначала раскладываются на последовательность битов, а потом каждый бит сравнивается и в результирующую последовательность битов записывается результат каждого сравнения.

Операция Название и значение Пример
& Битовое "И", проверяет равен ли бит 1 в обоих случаях. 0b0001 & 0b01010b0001
| Битовое "ИЛИ", проверяет равен ли бит 1 хотя бы в одном случае 0b0001 | 0b01010b0101
^ Битовое "Исключительное ИЛИ" возвращает 1 если бит равен 1 только в одном из операндов, но не в обоих сразу. 0b0001 ^ 0b01010b0100
~ Инвертирующий оператор. Каждый бит меняет на противоположное значение, принимает только правый операнд 1 ~0b1110-0b1111
<< Побитовый сдвиг влево биты левого операнда сдвигаются на количество позиций в правом операнде 2 0b1110 << 2'0b111000'
>> Побитовый сдвиг вправо биты левого операнда сдвигаются на количество позиций указанных в правом операнде 3 0b1110 >> 20b0011

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

Помните шутку когда вас просят быстро ответить на вопрос: сколько будет 2+2*2? С точки зрения правил математики правильный ответ 6, потому что у операции умножения приоритет выше чему у операции сложения:

>>> 2+2*2
6

Чтобы не попасться на удочку проще всего ставить знаки скобок и тогда всегда видно что выполняется раньше:

>>> (2+2)*2
8
>>> 2+(2*2)
6

Но даже если вы не поставите скобки, то у операторов есть приоритет. Посмотрите на данное выражение, как вы думаете какой должен быть ответ?

>>> (2+2)*2 > 2+(2*2)

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

>>> (2+2)*2 > 2+(2*2)
True

В официальной документации есть полная таблица приоритетов, от наименее приоритетных до наиболее приоритетных:

Оператор Описание
lambda Лямбда выражение
if <if_expr> -- !else Проверка условий
or Логическое OR
and Логическое AND
not x Логическое NOT
in, not in, is, is not,
<, <=, >, >=, !=, ==
Сравнения, включая вхождение во множество и проверку тождественности
| Битовое ИЛИ (OR)
^ Битовое исключающее ИЛИ (XOR)
& Битовое И (AND)
<<, >> Сдвиг
+, - Сложение и вычитание
*, @, /, //, % Умножение, умножение матриц, деление, остаток и целочисленное деление
+x, -x, ~x Позитивное, негативное и битовое НЕ (NOT)
** Возведение в степень
await x Await выражение
x[index], x[index:index],
x(arguments...), x.attribute
Получение элемента и элементов множества, обращение к атрибутам
(expressions...),
[expressions...],
{key: value...},
{expressions...}
Получение элемента кортежа, списка, словаря, множества
() Скобки

Ссылки


  1. Из за особенностей записи чисел инвертирующий оператор ~ затрагивает бит знака числа. Поэтому результат на самом деле результат проще представить по этой формуле -x - 1

  2. Тот же результат можно получить по формуле x << yx * (2**y) 

  3. Тот же результат можно получить по формуле x >> yx // (2**y)