Выполнение операций над операндами разных типов
Возможно, это был просто раздел статьи об операторах, которую я написал некоторое время назад, поскольку она очень сильно затрагивает тему операторов Python, но я подумал, что она заслуживает отдельной статьи, потому что я считаю эту тему довольно важной и поэтому, если эта часть информации находится в какой-то другой статье как часть какой-то другой темы, как бы отдаленно они ни были связаны, это может потенциально упустить из виду то, что я считаю довольно простой, но важной вещью, которую нужно знать о Python и о том, как он работает при работе с операнды разных типов.
Смешивание типов — это вещь в Python, которая возникает, когда выражение содержит два или более операнда разных типов. Каким-то образом это выражение должно быть оценено, а для этого необходимо установить точки соприкосновения. Рассмотрим самый простой из случаев, когда задействованы некоторые арифметические операции и пара типов операндов:
# define an integer a = 3 # define a float number b = 1.5 # add the two and store it in another variable c = a + b print(f"{type(a)}: {a}") print(f"{type(b)}: {b}") print(f"{type(c)}: {c}") Output: <class 'int'>: 3 <class 'float'>: 1.5 <class 'float'>: 4.5
Что сейчас произошло? Итак, когда мы сложили два числа, целое внутренне преобразовалось в float
, затем сложение было выполнено как между двумя числами с плавающей запятой. Как следствие, результат имеет тип float
.
Теперь это может быть или не быть лучшим случаем для демонстрации смешивания типов, потому что можно утверждать, что результат сложения не может быть сохранен ни в чем кроме переменной с плавающей запятой, поэтому давайте рассмотрим это следующий:
# define an integer a = 4 # define a float number b = 1.5 # multiply the two and store it in another variable c = a * b print(f"{type(a)}: {a}") print(f"{type(b)}: {b}") print(f"{type(c)}: {c}") Output: <class 'int'>: 4 <class 'float'>: 1.5 <class 'float'>: 6.0
На этот раз правило довольно ясное. Целое число было преобразовано в число с плавающей запятой, затем произошло умножение. Тип результата — тип с плавающей запятой, хотя на этот раз он вполне может вписаться в целочисленную переменную. Одно правило становится очень ясным: тип результата идентичен типу самого сложного оператора. В этом случае самый сложный оператор имеет тип float
, поэтому результат также будет иметь этот тип.
Имея в виду эти два приведенных выше примера, мы можем теперь заключить, что для того, чтобы Python мог успешно вычислить одно такое выражение, содержащее несколько типов операндов, он сначала преобразует их все в тип самого сложного, а затем выполняет операции это необходимо, в соответствии с правилами этого типа операнда.
Преобразование выполняется, как я уже упоминал выше, к наиболее сложному типу операнда в выражении по очевидной причине предотвращения потери данных. Представьте, если бы нам пришлось добавить целое число к числу с плавающей запятой:
a = 2 b = 3.7 print(float(a)) print(int(b)) Output: 2.0 3
Добавление a + b
в этом случае приведет к 5.7
, а результат будет типа float
, потому что Python преобразовал целое число a
в число с плавающей запятой, что упростило операцию сложения, поскольку оба операнда должны быть совместимы друг с другом и без потерь. данных произошло. Но представьте, если бы Python преобразовывал все операнды не в самый сложный, а в самый простой тип операнда — в нашем случае в целое число. a + b
даст нам результат 5
. Но мы бы потеряли 0.7
из-за преобразования числа с плавающей запятой в целое число.
Конечно, есть способы переопределить это поведение. Python предлагает несколько удобных функций преобразования типов, таких как int()
, float()
или complex()
. Они используются для преобразования переменных в (или создания) целых, числа с плавающей запятой и комплексных чисел соответственно.
Рассмотрим следующий пример:
a = 2 b = 3.7 c = 4.4 d = a + b + c e = a + int(b) + int(c) f = int(a + b + c) print(f"{type(d)}: {d}") print(f"{type(e)}: {e}") print(f"{type(f)}: {f}") Output: <class 'float'>: 10.100000000000001 <class 'int'>: 9 <class 'int'>: 10
Сначала мы определили 3 числовые переменные: целое число a
и 2 числа с плавающей запятой, b
и c
.
Затем мы просто сложили их вместе и сохранили результат в d
, тип которого, как мы видели, был float
, а его значение было 10.1
. Это связано с тем, что за кулисами Python преобразовал a
в float
, а затем выполнил 2.0 + 3.7 + 4.4
и в результате получил 10.1
.
Второй тест, который мы сделали, заключался в том, чтобы переопределить неявное преобразование a
в float
путем явного преобразования b
и c
в int
. Обратите внимание, как преобразование float
в int
эффективно отбрасывает все, что находится справа от десятичной точки? Вот почему мы получаем только 9
, когда суммируем их. 2 + 3 + 4
— это сумма усеченных переменных.
Наконец, третий тест заключался в том, чтобы суммировать их все в соответствии с текущими встроенными правилами преобразования типов только для того, чтобы затем явно преобразовать его в int
. Результат неудивительный 10
. Все три переменные были выровнены по типу, что означает, что a
было неявно преобразовано в float
, затем, как видно из первого теста, произошло суммирование: 2.0 + 3.7 + 4.4
, в результате получилось значение 10.1
, которое стало 10
посредством явного преобразования int()
функция.
Другое популярное название, под которым вы найдете явное преобразование, — приведение типов. Итак, вне зависимости от названия, это одно и то же: мы, программисты, используем такие функции, как int()
, float()
или complex()
, для явного преобразования некоторого значения из одного типа в другой. Другими словами, приведение типов выполняется разработчиком, и это также видно в коде. Другими словами, всякий раз, когда мы приводим тип, ответственность за любые потери данных, которые может понести этот процесс приведения типов, ложится на наши плечи.
С другой стороны, у нас есть неявные преобразования, которые Python выполняет под капотом, чтобы предотвратить потерю данных и иметь возможность правильно вычислять выражения, содержащие несколько типов операндов. Они не прописаны явно в нашем коде, но случаются, если только мы не противодействуем этому приведением типов.
Надо сказать, что не все операторы в Python допускают смешивание типов. Есть ограниченное количество операторов, которые это позволяют. Они разделены на 2 категории:
- арифметические операторы:
+
,-
,*
,/
,//
,%
,**
; - операторы сравнения:
<
,>
,<=
,>=
,==
,!=
.
Я оставлю вам простой пример смешивания типов с использованием операторов сравнения:
print(2.0 == 2) Output: True
Механизм включился и, как всегда, преобразовал целочисленное значение в значение с плавающей запятой, а затем выполнил сравнение между двумя совместимыми значениями, чтобы получить результат True
.
Короче говоря, это почти то, чем мне пришлось поделиться на тему смешивания типов в Python. Надеюсь, вы, ребята, хорошо прочитали и до следующего раза! Оставайтесь в безопасности и счастливого кодирования!
Дак — инженер-программист, наставник, писатель и иногда даже учитель. Обладая более чем 12-летним опытом разработки программного обеспечения, он теперь является настоящим сторонником языка программирования Python, а его страстью является помощь людям в оттачивании их навыков Python и программирования в целом. Вы можете связаться с колодой в Linkedin, Facebook, Twitter и Discord: Deck451#6188, а также следить за его публикациями здесь, на Medium.