Преобразование типов в JavaScript | by Serj Bulavyk
Know your engines!
Перевод статьи Alexey Samoshkin “JavaScript type coercion explained”.
Преобразование типов это процесс конвертации значения из одного типа в другой (как например, строки в число, объекта к булевому значению и т. д.). Любой тип, будь то примитив или объект, может быть преобразован в другой тип. Для справки, примитивы это: number
, string
, boolean
, null
, undefined
+ Symbol
(добавлен в ES6).
В качестве примера преобразования типов, можно ознакомиться с JavaScript Comparison Table, где продемонстрировано как ведёт себя оператор нестрогого сравнения ==
для разных типов a
и b
.
Из-за побочного эффекта оператора ==
в виде неявного приведения типа, эта матрица выглядит довольно пугающей, и запомнить все эти комбинации не представляется возможным. К счастью, вам не обязательно это делать, достаточно просто знать принципы, которые лежат в основе преобразования типов.
Эта статья подробно расскажет вам о том, как работает механизм преобразования типов в JavaScript и вооружит вас необходимыми знаниями для того, что-бы вы могли самостоятельно объяснить как вычисляются и каков будет результат следующих выражений. В конце статьи я продемонстрирую ответы и объясню их.
true + false
12 / "6"
"number" + 15 + 3
15 + 3 + "number"
[1] > null
"foo" + + "bar"
'true' == true
false == 'false'
null == ''
!!"false" == !!"true"
[‘x’] == ‘x’
[] + null + 1
[1,2,3] == [1,2,3]
{}+[]+{}+[1]
!+[]+[]+![]
new Date(0) - 0
new Date(0) + 0
Этот список скорее представляет собой те вещи, которые вам как программисту делать не стоит, а поэтому расценивайте этот список как своеобразные упражнения, для того чтобы оценить насколько хорошо вы знаете механизм приведения типов. Если вам станет скучно, вы можете найти больше примеров на wtfjs. com.
Кстати, иногда вы можете встретить подобные вопросы на собеседованиях на позицию JavaScript разработчика. Итак, поехали дальше 🙂
Явное и неявное преобразование
Преобразование типов может происходить явно и неявно.
Когда разработчик хочет намеренно произвести преобразование типов, написав, к примеру Number(value)
, это называется явным преобразованием типов (или type casting).
Так как JavaScript это слабо типизированный язык, преобразование между разными типами может происходить автоматически, и это называется неявным преобразованием типов. Чаще всего это происходит когда вы применяете операторы к значениям разных типов, таких как 1 == null
, 2 / `5`
, null + new Date()
, может происходить в зависимости от контекста, как например, в случае с if (value) {…}
, где value будет приведено к булевому значению.
Оператор строгого равенства ===
не приводит к неявному преобразованию типов. Оператор нестрогого равенства ==
, в свою очередь, производит сравнение операндов и, если требуется, неявное преобразование типов.
Неявное преобразование типов — это палка о двух концах: с одной стороны это источник проблем и разочарований, а с другой — механизм, который позволяет нам писать меньше кода, не теряя при этом читабельности.
Три типа конвертации
Во-первых, следует знать, что в JavaScript существует всего 3 типа преобразования:
- строковое
- булевое
- численное
Во-вторых, логика преобразования для примитивов и объектов работает по-разному, но, и примитивы и объекты могут быть преобразованы только этими тремя способами.
Давайте сначала разберёмся с примитивами.
Приведение к строке
Для явного приведения значения к строке необходимо применить к нему функцию String()
. Неявное преобразование будет вызвано бинарным оператором +
, кода один из операндов является строкой:
String(123) // explicit
123 + '' // implicit
Все примитивы будут приведены к строке вполне естественно, как вы могли и ожидать:
String(123) // '123'
String(-12. 3) // '-12.3'
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(false) // 'false'
Преобразование символов происходит немного сложнее, потому что они могут быть преобразованы только явным образом. Вы можете прочитать об этих правилах подробнее здесь.
String(Symbol('my symbol')) // 'Symbol(my symbol)'
'' + Symbol('my symbol') // TypeError is thrown
Булевое преобразование
Для явного преобразования к булевому значению, нужно применить функцию Boolean()
. Неявное преобразование происходит в логическом контексте if (val) { … }
или при применении логических операторов (||
&&
!
).
Boolean(2) // explicit
if (2) { ... } // implicit due to logical context
!!2 // implicit due to logical operator
2 || 'hello' // implicit due to logical operator
На заметку, логические операторы такие как ||
и &&
производят булевое преобразование под капотом, но при этом всегда возвращают оригинальное значение операндов, даже если они не являются булевыми.
// returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123; // x === 123
Поскольку существует всего два возможных результата преобразования, легче просто запомнить список ложных значений:
Boolean('') // false
Boolean(0) // false
Boolean(-0) // false
Boolean(NaN) // false
Boolean(null) // false
Boolean(undefined) // false
Boolean(false) // false
Любое значение, которое не вошло в этот список, будет преобразовано в true
, включая объекты, функции, Array
, Date
и так далее. Символы, пустые объекты и массивы так же будут иметь значение true
.
Boolean({}) // true
Boolean([]) // true
Boolean(Symbol()) // true
!!Symbol() // true
Boolean(function() {}) // true
Численное преобразование
Для явного преобразования к числу нужно применить функцию Number()
, точно так же, как мы делали с Boolean()
и String()
. ~
)
-
+
*
/
%
). Обратите внимание, что бинарный оператор +
не вызывает численного преобразования, если один из операндов является строкой+
==
(включая !=
). Обратите внимание, что данный оператор не вызывает численное преобразование, если оба операнда являются строкамиNumber('123') // explicit
+'123' // implicit
123 != '456' // implicit
4 > '5' // implicit
5/null // implicit
true | 0 // implicit
Примеры того, как примитивы будут преобразованы в числа:
Number(null) // 0
Number(undefined) // NaN
Number(true) // 1
Number(false) // 0
Number(" 12 ") // 12
Number("-12.34") // -12. 34
Number("\n") // 0
Number(" 12s ") // NaN
Number(123) // 123
При преобразовании строки в число, движок сначала отсекает все пробельные символы, символы \n
, и \t
в начале и в конце строки, и возвращает NaN
если обрезанная строка не представляет из себя корректное число. Если строка окажется пустой, то результатом будет 0
.
null
и undefined
обрабатываются по разному: null
станет 0
, в то время как undefined
станет NaN
.
Численное преобразование, как явное так и неявное, не работает для символов. Более того, движок бросает ошибку TypeError
, вместо того, чтобы по-тихому преобразовать Symbol
в NaN
, как это происходит с undefined
. Подробнее о правилах преобразования символов можно посмотреть на MDN.
Number(Symbol('my symbol')) // TypeError is thrown
+Symbol('123') // TypeError is thrown
Существует два специальных правила которые следует запомнить:
- При применении
==
кnull
илиundefined
, численное преобразование не происходит, так какnull
может равняться толькоnull
илиundefined
, и ничему другому.
null == 0 // false, null is not converted to 0
null == null // true
undefined == undefined // true
null == undefined // true
2. NaN
не равен ничему, даже самому себе.
if (value !== value) { console.log("we're dealing with NaN here") }
Преобразование типов для объектов
До текущего момента мы рассматривали преобразования для примитивов, что является достаточно банальным.
Когда дело доходит до объектов, и движок встречает выражение вроде [1] + [2, 3]
, ему сначала необходимо привести объекты к примитивным значениям, а уже потом выполнить финальное преобразование. Как и в случае с примитивами, объект может быть преобразован всего тремя способами: численным, строковым, булевым.
Самый простой пример это булевое преобразование — любое не примитивное значение всегда приводится к true
, включая пустые объекты и массивы.
Объекты приводятся к примитивам посредством вызова внутреннего метода [[ToPrimitive]]
, который отвечает как за численное, так и за строковое преобразование.
Вот псевдокод реализации метода [[ToPrimitive ]]
:
Методу [[ToPrimitive]]
передаётся два аргумента: входящее значение и предпочтительный тип для преобразования: Number
или String
. Второй аргумент является опциональным.
Как для строкового так и для численного преобразования используются два метода объекта: valueOf
и toString
. Оба метода объявлены в Object.prototype
, а значит доступны для всех производных типов, таких как Date
, Array
и т.д.
В общих чертах алгоритм выглядит следующим образом:
- Если входящее значение уже является примитивом, ничего не делать и просто вернуть его.
- Вызвать
input.toString()
, если результат примитив — вернуть его. - Вызвать
input.valueOf()
, если результат примитив — вернуть его. - Если ни один из методов не вернул примитив — бросить ошибку
TypeError
.
При численном преобразовании сначала вызывается метод valueOf()
, а уже затем toString()
. При строковом преобразовании наоборот — сначала происходит вызов toString()
, а уже потом valueOf()
.
Большинство встроенных типов не имеют метода valueOf
или же имеют valueOf
, который возвращает свой собственный объект this
, который игнорируется, так как this
не является примитивом. Вот почему численное и строковое преобразование в большинстве случаев работает одинаково — оба в конечном итоге вызывают метод toString()
.
Разные операторы могут вызывают строковое или численное преобразование при помощи параметра preferredType
. Но существует два исключения: нестрогое равенство ==
и бинарный оператор +
, которые вызывают режим преобразования по умолчанию (preferredType
не указан или равен default
). В таком случае, большинство встроенных типов подразумевают численное преобразование, за исключением Date
, который предпочитает строковое преобразование.
Вот пример преобразования Date
:
Вы можете переопределить методы toString()
и valueOf()
для того, чтобы повлиять на логику преобразования объектов в примитив.
Обратите внимание, как obj + ‘’
возвращает строку 101
. Оператор +
вызывает преобразование в режиме по умолчанию, и как упоминалось выше, Object
подразумевает численное преобразование в таком случае, используя сначала метод valueOf()
, а затем уже toString()
.
Метод ES6 Symbol.toPrimitive
В ES5 вы можете повлиять на логику преобразования объекта в примитив, переопределив методы toString()
и valueOf()
.
В ES6 вы можете пойти дальше и полностью заменить внутреннюю процедуру метода [[ToPrimitive]]
, реализовав метод [Symbol.toPrimitive]()
у объекта.
Примеры
Вооружившись теорией, давайте вернёмся к нашим примерам:
true + false // 1
12 / "6" // 2
"number" + 15 + 3 // 'number153'
15 + 3 + "number" // '18number'
[1] > null // true
"foo" + + "bar" // 'fooNaN'
'true' == true // false
false == 'false' // false
null == '' // false
!!"false" == !!"true" // true
['x'] == 'x' // true
[] + null + 1 // 'null1'
[1,2,3] == [1,2,3] // false
{}+[]+{}+[1] // '0[object Object]1'
!+[]+[]+![] // 'truefalse'
new Date(0) - 0 // 0
new Date(0) + 0 // 'Thu Jan 01 1970 02:00:00(EET)0'
Ниже представлен детальный разбор того, как вычисляется каждое из выражений.
Бинарный оператор +
вызывает численное преобразование для true
и false
:
true + false
==> 1 + 0
==> 1
Оператор деления /
вызывает численное преобразование строки 6
:
12 / '6'
==> 12 / 6
==>> 2
Оператор +
выполняется слева направо, поэтому сначала выполнится выражение “number” + 15
. Поскольку один из операндов это строка, оператор +
вызовет строковое преобразование числа 15
и последующую конкатенацию двух строк. На следующем этапе выражение “number15” + 3
выполнится таким же образом.
“number” + 15 + 3
==> "number15" + 3
==> "number153"
Сначала выполняется сложение чисел 15 + 3
. На данном этапе никакого преобразования не нужно, так как оба операнда являются числами. Затем выполняется выражение 18 + ‘number’
, и так как один из операндов является строкой, то вызывается строковое преобразование для числа 18
, и последующая конкатенация двух строк.
15 + 3 + "number"
==> 18 + "number"
==> "18number"
Оператор сравнения >
вызывает численное преобразование для [1]
и null
[1] > null
==> '1' > 0
==> 1 > 0
==> true
Унарный оператор +
имеет более высокий приоритет чем бинарный оператор +
. Поэтому выражение + 'bar'
выполняется первым. Унарный плюс вызывает численное преобразования строки bar
. Так как эта строка не представляет собой корректное число, результатом будет NaN
. Следующим шагом выполнится выражение 'foo' + NaN
.
"foo" + + "bar"
==> "foo" + (+"bar")
==> "foo" + NaN
==> "fooNaN"
Оператор сравнения ==
вызывает численное преобразование, поэтому строка true
конвертируется в NaN
, а правый операнд true
станет 1
.
'true' == true
==> NaN == 1
==> falsefalse == 'false'
==> 0 == NaN
==> false
Оператор ==
обычно вызывает численное преобразование, но не в случае с null
. Действует исключение из правил: null
равен только null
или undefined
и ничему другому.
null == ''
==> false
Оператор !!
конвертирует строки true
и false
в булевое значение true
, так как это не пустые строки. А дальше оператор ==
просто сравнивает два булевых значения безо всяких преобразований.
!!"false" == !!"true"
==> true == true
==> true
Оператор ==
вызывает численное преобразование для массива. Метод массива valueOf()
возвращает сам массив, а значит результат игнорируется, так как не является примитивом. Далее, вызывается метод массива toString()
, который конвертирует [‘x’]
в строку ‘x’
.
['x'] == 'x'
==> 'x' == 'x'
==> true
Оператор +
вызывает численное преобразование массива. Метод массива valueOf()
вернёт сам массив, поэтому результат игнорируется, поскольку не является примитивом.
Далее выполняется выражение ’’ + null + 1
.
[] + null + 1
==> '' + null + 1
==> 'null' + 1
==> 'null1'
Логические операторы ||
и &&
преобразовывают операнды к булевому значению, но всегда возвращают оригинальное значение операнда (не булевое). 0
станет false
, а поскольку 0
является не пустой строкой, то конвертируется в true
. {}
пустой объект тоже становится true
.
0 || "0" && {}
==> (0 || "0") && {}
==> (false || true) && true // internally
==> "0" && {}
==> true && true // internally
==> {}
В данном примере никакого преобразования не требуется, потому что оба операнда одного типа. Так как оператор ==
сравнивает объекты по ссылке, а не по значению, а данные массивы являются двумя разными экземплярами, результатом будет false
.
[1,2,3] == [1,2,3]
==> false
Все операнды являются не примитивами, поэтому +
вызывает численное преобразование. Методы Object.valueOf()
и Array.valueOf()
возвращают самих себя, соответственно будут проигнорированы. В качестве запасного варианта, вызывается метод toString()
. Трюк в том, что первый {}
воспринимается движком не как создание объекта, а как объявление пустого блока кода и поэтому игнорируется. Выполнение начинается с выражения +[]
, которое преобразуется в пустую строку посредством метода toString()
, и далее в 0
.
{}+[]+{}+[1]
==> +[]+{}+[1]
==> 0 + {} + [1]
==> 0 + '[object Object]' + [1]
==> '0[object Object]' + [1]
==> '0[object Object]' + '1'
==> '0[object Object]1'
Данный пример лучше объяснить пошагово с точки зрения приоритета выполнения операторов:
!+[]+[]+![]
==> (!+[]) + [] + (![])
==> !0 + [] + false
==> true + [] + false
==> true + '' + false
==> 'truefalse'
Оператор -
вызывает численное преобразование для объекта Date
. Date.valueOf()
возвращает количество миллисекунд прошедших с начала Unix эпохи (в данном случае 0
).
new Date(0) - 0
==> 0 - 0
==> 0
Оператор +
вызывает преобразование по умолчанию. Date
, как исключение, подразумевает строковое преобразование, поэтому используется метод toString()
, а не valueOf()
.
new Date(0) + 0
==> 'Thu Jan 01 1970 02:00:00 GMT+0200 (EET)' + 0
==> 'Thu Jan 01 1970 02:00:00 GMT+0200 (EET)0'
Источники
Я бы хотел порекомендовать отличную книгу “Understanding ES6” написанную Nicholas C. Zakascholas. Книга является отличным ресурсом для изучения ES6 с достаточным уровнем освещения: не слишком поверхностно, и в тоже время не погружается в механику работы движка черезчур.
Ещё одна отличная книга, на этот раз по ES5 — SpeakingJS написанная Axel Rauschmayer.
Современный учебник Javascript — https://learn.javascript.ru/,
в особенности эти две страницы, посвящённые преобразованию типов.
JavaScript Comparison Table — https://dorey.github.io/JavaScript-Equality-Table/
wtfjs — небольшой блог о языке, который мы все так любим, не смотря на то что он дает много поводов его ненавидеть — https://wtfjs.com/
Преобразование типов — JavaScript — Дока
Кратко
Скопировано
Представим ситуацию: у нас есть форма с полем, в которое пользователь вписывает свой возраст в годах.
По умолчанию любой ввод в полях — это строка. Если мы хотим работать с этим значением, как с числом, то нам нужно привести его к числу.
Приведение (или преобразование) типов — это процесс конвертации значения из одного типа в другой.
В JavaScript типы можно преобразовывать явно и неявно.
Когда мы вызываем функцию, чтобы получить конкретный тип — это явное преобразование:
const x = '4'Number(x)const y = 4String(y)
const x = '4'
Number(x)
const y = 4
String(y)
Сравнение бывает строгим и нестрогим. При строгом сравнении (=
) интерпретатор учитывает типы сравниваемых значений.
Когда же мы сравниваем значения нестрого между собой с помощью =
, JavaScript приводит типы самостоятельно:
console.log(5 == '5')// trueconsole.log(5 === '5')// false
console.log(5 == '5')
// true
console.log(5 === '5')
// false
Чтобы понять, почему так, нам надо сперва разобраться, какие типы в JS есть.
Сперва проведём границу между примитивными типами, объектами и другими.
Примитивные типы
Скопировано
В JavaScript примитивные типы следующие:
// 1. Undefinedtypeof undefined === 'undefined'// 2. Boolean, логическийtypeof true === 'boolean'typeof false === 'boolean'// 3. Number, числоtypeof 42 === 'number'typeof 4.2 === 'number'typeof -42 === 'number'typeof Infinity === 'number'typeof -Infinity === 'number'// 4. String, строкаtypeof '' === 'string'typeof 'string' === 'string'typeof 'number' === 'string'typeof 'boolean' === 'string'// 5. Symbol, символ, ES6typeof Symbol() === 'symbol'// 6. BigInt, большое число, ES6typeof 9007199254740991n === 'bigint'typeof BigInt(9007199254740991) === 'bigint'// 7. Nulltypeof null === 'object'// О том, почему здесь “object” — чуть позже.
// 1. Undefined
typeof undefined === 'undefined'
// 2. Boolean, логический
typeof true === 'boolean'
typeof false === 'boolean'
// 3. Number, число
typeof 42 === 'number'
typeof 4.2 === 'number'
typeof -42 === 'number'
typeof Infinity === 'number'
typeof -Infinity === 'number'
// 4. String, строка
typeof '' === 'string'
typeof 'string' === 'string'
typeof 'number' === 'string'
typeof 'boolean' === 'string'
// 5. Symbol, символ, ES6
typeof Symbol() === 'symbol'
// 6. BigInt, большое число, ES6
typeof 9007199254740991n === 'bigint'
typeof BigInt(9007199254740991) === 'bigint'
// 7. Null
typeof null === 'object'
// О том, почему здесь “object” — чуть позже.
Примитивные типы — это такие типы, значения которых можно только перезаписать, но нельзя изменить.
Например, если мы создали переменную со значением 42
, изменить это значение будет нельзя. Мы сможем его только полностью перезаписать:
let theAnswerToUltimateQuestion = 42theAnswerToUltimateQuestion = 43// Новое значение полностью перезаписало старое;// старое собрано сборщиком мусора и забыто.let theAnswers = [42, 43, 44]theAnswers[0] = 142// Теперь значение переменной [142, 43, 44];// мы не перезаписали его полностью, а лишь изменили часть.
let theAnswerToUltimateQuestion = 42
theAnswerToUltimateQuestion = 43
// Новое значение полностью перезаписало старое;
// старое собрано сборщиком мусора и забыто.
let theAnswers = [42, 43, 44]
theAnswers[0] = 142
// Теперь значение переменной [142, 43, 44];
// мы не перезаписали его полностью, а лишь изменили часть.
Этот механизм связан с тем, как значения переменных хранятся в памяти. Мы не пойдём слишком глубоко в эту тему, но, грубо говоря, примитивные типы «ссылаются на одно и то же значение в памяти», а не примитивные — на разные. Этот вопрос мы разбираем подробнее в статье «Хранение по ссылке и по значению »
Из-за этого, например, примитивы можно сравнивать по значению:
const a = 5const b = 5console.log(a == b)// true
const a = 5
const b = 5
console.log(a == b)
// true
А вот не примитивы — не получится:
const a = [1, 2, 3]const b = [1, 2, 3]console.log(a == b)// false
const a = [1, 2, 3]
const b = [1, 2, 3]
console.log(a == b)
// false
Даже несмотря на то, что массивы содержат одни и те же числа, при сравнении они не являются «одинаковыми». Когда JavaScript сравнивает
и b
, он, грубо говоря, «сравнивает места в памяти, на которые ссылаются эти переменные». У не примитивов, эти места — разные, из-за чего они считаются неодинаковыми.
Объекты
Скопировано
Объекты в JavaScript используются для хранения коллекций значений.
Массивы (Array) в JS — тоже объекты.
Как мы уже говорили, не примитивы сравниваются по ссылке, а не по значению. Объекты и массивы — это как раз не примитивы.
У объектов в JavaScript собственный тип — object
.
const keyValueCollection = { key: 'value' }typeof keyValueCollection === 'object'const listCollection = [1, 2, 3]typeof listCollection === 'object'
const keyValueCollection = { key: 'value' }
typeof keyValueCollection === 'object'
const listCollection = [1, 2, 3]
typeof listCollection === 'object'
У null
оператор typeof
возвращает 'object'
, хотя это тоже примитив:
console.log(typeof null === 'object')// true
console.log(typeof null === 'object')
// true
Функции
Скопировано
У функций в JavaScript тоже тип — object
, хотя typeof
возвращает 'function'
:
function simpleFunction() {}console. log(typeof simpleFunction === 'function')// trueconst assignedFunction = function () {}console.log(typeof assignedFunction === 'function')// trueconst arrowFunction = () => {}console.log(typeof arrowFunction === 'function')// trueconsole.log(typeof function () {} === 'function')// truefunction simpleFunction() {} console.log(typeof simpleFunction === 'function') // true const assignedFunction = function () {} console.log(typeof assignedFunction === 'function') // true const arrowFunction = () => {} console.log(typeof arrowFunction === 'function') // true console.log(typeof function () {} === 'function') // true
Разницу между разными видами функций мы описали в статье «Функции».
typeof
Скопировано
Оператор typeof
возвращает не непосредственно «тип», а строку. Для всех примитивов, кроме null
, этой строкой будет название этого примитива.
Для объектов он сначала проверит, можно ли его «вызвать». Функции — это как раз такие объекты, поэтому оператор возвращает function
.
Несмотря на то, что typeof
не всегда возвращает то, что мы бы могли ожидать, им удобно пользоваться в некоторых случаях в коде, например, для определения функций.
Преобразование типов
Скопировано
Теперь, когда мы разобрались с типами, посмотрим, как мы можем преобразовывать значения одного типа в значения другого.
В JavaScript существует лишь 3 типа конвертации: в строку, в число или в логическое значение.
Чтобы конвертировать значение в эти типы, можно воспользоваться одноимёнными функциями:
String(42) // Приводит к строке.Number('42') // Приводит к числу.Boolean(42) // Приводит к логическому значению.
String(42) // Приводит к строке.
Number('42') // Приводит к числу.
Boolean(42) // Приводит к логическому значению.
Приведение к строке, числу и логическому значению можно проводить над любыми значениями:
// К строке:String(123) // '123'String(-12. 3) // '-12.3'String(null) // 'null'String(undefined) // 'undefined'String(true) // 'true'String(false) // 'false'String(function () {}) // 'function () {}'String({}) // '[object Object]'String({ key: 42 }) // '[object Object]'String([]) // ''String([1, 2]) // '1,2'
// К строке:
String(123) // '123'
String(-12.3) // '-12.3'
String(null) // 'null'
String(undefined) // 'undefined'
String(true) // 'true'
String(false) // 'false'
String(function () {}) // 'function () {}'
String({}) // '[object Object]'
String({ key: 42 }) // '[object Object]'
String([]) // ''
String([1, 2]) // '1,2'
К числу также можно пытаться приводить любые значения. Если JavaScript не сможет привести какое-то значение к числу, мы получим
— особое значение, представляющее не-число (Not-a-Number).
// К числу:Number('123') // 123Number('123.4') // 123.4Number('123,4') // NaNNumber('') // 0Number(null) // 0Number(undefined) // NaNNumber(true) // 1Number(false) // 0Number(function () {}) // NaNNumber({}) // NaNNumber([]) // 0Number([1]) // 1Number([1, 2]) // NaN// Обратите внимание, что Number от пустого массива — 0,// от массива с одним числом — это число// и от массива с несколькими числами — NaN. // Почему так происходит, мы поймём чуть ниже.
// К числу:
Number('123') // 123
Number('123.4') // 123.4
Number('123,4') // NaN
Number('') // 0
Number(null) // 0
Number(undefined) // NaN
Number(true) // 1
Number(false) // 0
Number(function () {}) // NaN
Number({}) // NaN
Number([]) // 0
Number([1]) // 1
Number([1, 2]) // NaN
// Обратите внимание, что Number от пустого массива — 0,
// от массива с одним числом — это число
// и от массива с несколькими числами — NaN.
// Почему так происходит, мы поймём чуть ниже.
К логическому также можно приводить любые значения:
Boolean('') // falseBoolean('string') // trueBoolean('false') // trueBoolean(0) // falseBoolean(42) // trueBoolean(-42) // trueBoolean(NaN) // falseBoolean(null) // falseBoolean(undefined) // falseBoolean(function () {}) // trueBoolean({}) // trueBoolean({ key: 42 }) // trueBoolean([]) // trueBoolean([1, 2]) // true// Грубо говоря, всё, кроме пустой строки, нуля,// NaN, null и undefined — true.Boolean('') // false Boolean('string') // true Boolean('false') // true Boolean(0) // false Boolean(42) // true Boolean(-42) // true Boolean(NaN) // false Boolean(null) // false Boolean(undefined) // false Boolean(function () {}) // true Boolean({}) // true Boolean({ key: 42 }) // true Boolean([]) // true Boolean([1, 2]) // true // Грубо говоря, всё, кроме пустой строки, нуля, // NaN, null и undefined — true.
Неявное преобразование типов
Скопировано
В секции выше мы преобразовывали типы «руками», с помощью функций. Но JavaScript может делать такие преобразования за нас самостоятельно. (Из-за чего в языке появляется много странностей, за которые его не очень сильно любят.)
Такая типизация, при которой тип значения определяется во время присвоения, а по ходу программы может меняться, — называется динамической.
Неявное преобразование происходит, когда мы заставляем JavaScript работать со значениями разных типов. Например, если мы хотим «сложить» число и строку:
5 + '3' === '53'5 - '3' === 25 + '-3' === '5-3'5 - +3 === 25 + -3 === 2// Из-за этого же появилась и такая шутка:Array(16).join('wat' - 1) + ' Batman!'// 'NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN Batman!'
5 + '3' === '53'
5 - '3' === 2
5 + '-3' === '5-3'
5 - +3 === 2
5 + -3 === 2
// Из-за этого же появилась и такая шутка:
Array(16).join('wat' - 1) + ' Batman!'
// 'NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN Batman!'
Дело в том, как JavaScript пробует эти два типа «сопоставить» друг с другом, чтобы с ними работать.
Вначале посмотрим на примитивы.
- Интерпретатор приведёт примитивные значения к логическим, если мы используем
&&
или||
. - К строке, если мы используем
+
, когда один из операндов — строка. - К числу, если:
- мы используем операторы сравнения
<
,<
,= >
,>
;= - используем арифметические операции
-
,+
(за исключением пункта 2),/
,*
. - используем унарный плюс:
+'2'
;= = = 2 - используем оператор нестрогого сравнения
=
.=
- мы используем операторы сравнения
Но примитивами дело не заканчивается, JavaScript также неявно приводит и не примитивные значения.
Интерпретатор приводит их к логическому, если мы используем &&
или ||
. Объекты — всегда true
.
С числом и строкой всё немного интереснее. Чтобы определить, к строке приводить значение или к числу, JavaScript смотрит, какой из двух методов (value
и to
) в текущем объекте объявлен.
- Если перед нами не объект
Date
, то методvalue
вызывается, обычно, первым (если не сильно углубляться в детали спецификации).Of ( ) - Если возвращённое после этого значение — это примитив, то возвращается оно.
- Если нет, то вызывается другой метод (если
value
не вернул примитив, то вызываетсяOf ( ) to
и наоборот).String ( ) - Если после этого вернулся примитив, возвращается он.
- Если даже после этого не вернулся примитив, то будет ошибка
Uncaught TypeError
.: Cannot convert object to primitive value
На примерах
Скопировано
// 1. Простой объектconst obj1 = {}obj1.valueOf() // {}obj1.toString() // '[object Object]'// Чтобы «сложить» число с объектом,// вначале будет вызван obj1.valueOf().// Он вернёт объект (непримитив),// после чего будет вызван obj1.toString().1 + obj1// 1 + '[object Object]'// '1' + '[object Object]'// '1[object Object]'// 2. Объект с указанным .valueOf()const obj2 = {}obj2. valueOf = () => 'obj2'obj2.valueOf() // 'obj2'obj2.toString() // '[object Object]'// Теперь, когда мы объявили метод .valueOf(),// при вызове он будет возвращать строку.// Так как строка — примитив,// она и будет использована при «сложении».1 + obj2// 1 + 'obj2'// '1' + 'obj2'// '1obj2'// 2.1. Если же мы будем возвращать числоconst obj2 = {}obj2.valueOf = () => 42obj2.valueOf() // 42obj2.toString() // '[object Object]'1 + obj2// 1 + 42// 43// 3. Датыconst date = new Date()date.valueOf() // 1467864738527date.toString() // 'Sun Sep 15 2019...'// У дат приоритет методов обратный:// то есть вначале будет вызываться .toString(),// и только после него — .valueOf().1 + date// 1 + 'Sun Sep 15 2019...'// '1' + 'Sun Sep 15 2019...'// '1Sun Sep 15 2019...'
// 1. Простой объект
const obj1 = {}
obj1.valueOf() // {}
obj1.toString() // '[object Object]'
// Чтобы «сложить» число с объектом,
// вначале будет вызван obj1.valueOf().
// Он вернёт объект (непримитив),
// после чего будет вызван obj1. toString().
1 + obj1
// 1 + '[object Object]'
// '1' + '[object Object]'
// '1[object Object]'
// 2. Объект с указанным .valueOf()
const obj2 = {}
obj2.valueOf = () => 'obj2'
obj2.valueOf() // 'obj2'
obj2.toString() // '[object Object]'
// Теперь, когда мы объявили метод .valueOf(),
// при вызове он будет возвращать строку.
// Так как строка — примитив,
// она и будет использована при «сложении».
1 + obj2
// 1 + 'obj2'
// '1' + 'obj2'
// '1obj2'
// 2.1. Если же мы будем возвращать число
const obj2 = {}
obj2.valueOf = () => 42
obj2.valueOf() // 42
obj2.toString() // '[object Object]'
1 + obj2
// 1 + 42
// 43
// 3. Даты
const date = new Date()
date.valueOf() // 1467864738527
date.toString() // 'Sun Sep 15 2019...'
// У дат приоритет методов обратный:
// то есть вначале будет вызываться .toString(),
// и только после него — .valueOf().
1 + date
// 1 + 'Sun Sep 15 2019...'
// '1' + 'Sun Sep 15 2019...'
// '1Sun Sep 15 2019...'
Строгое и нестрогое равенство
Скопировано
Неявное преобразование также используется, когда мы сравниваем значения через нестрогое равенство =
.
В отличие от строгого равенства (=
), в нём интерпретатор пробует привести типы к одному, чтобы сравнить.
Полный алгоритм сложный. Для удобства его свели в большую матрицу, которая показывает, «что чему равно» при строгом и нестрогом равенстве.
Вот таблица нестрогого равенства (зелёным отмечены значения, которые «равны»):
А вот — для строгого:
Хорошей практикой считается использовать только строгое сравнение, чтобы избежать неявного преобразования типов при сравнении.
На практике
Скопировано
Саша Беспоясов советует
Скопировано
Всегда используйте строгое равенство при сравнении значений.
🛠 Для удобства проверку на существование объекта можно проводить через if
, потому что объекты всегда приводятся к true
.
const exists = {}if (exists) { /* эта ветка выполнится */}const doesntExist = undefinedif (doesntExist) { /* эта ветка не выполнится */}
const exists = {}
if (exists) {
/* эта ветка выполнится */
}
const doesntExist = undefined
if (doesntExist) {
/* эта ветка не выполнится */
}
🛠 Если хочется описать сложную структуру, которая бы умела «вести себя», как число или строка, можно описать методы . value
или .to
.
const ticketPrice = { amount: 20, currency: 'USD', valueOf: () => 20, toString: () => '$20',}1 + ticketPrice // 1 + 20 -> 21console.log(ticketPrice)// $20
const ticketPrice = {
amount: 20,
currency: 'USD',
valueOf: () => 20,
toString: () => '$20',
}
1 + ticketPrice // 1 + 20 -> 21
console.log(ticketPrice)
// $20
На собеседовании
Скопировано
Это партнёрская рубрика, мы выпускаем её совместно с сервисом онлайн-образования Яндекс Практикум. Приносите вопрос, на который не знаете ответа, в задачи, мы разложим всё по полочкам и опубликуем. Если знаете ответ, присылайте пулреквест на GitHub.
❓
Чему будет равно значение переменной variable
: let variable
?
Скопировано
Это вопрос без ответа. Вы можете помочь! Почитайте о том, как контрибьютить в Доку.
Преобразование типов Python (с примерами)
В этом руководстве мы узнаем о преобразовании типов Python с помощью примеров.
В программировании преобразование типов — это процесс преобразования данных одного типа в другой. Например: преобразование данных int
в str
.
В Python существует два типа преобразования типов.
- Неявное преобразование — автоматическое преобразование типов
- Явное преобразование — ручное преобразование типов
Неявное преобразование типов Python
В определенных ситуациях Python автоматически преобразует один тип данных в другой. Это известно как неявное преобразование типов.
Пример 1: Преобразование целого числа в число с плавающей запятой
Давайте рассмотрим пример, в котором Python поддерживает преобразование младшего типа данных (целое) в более высокий тип данных (плавающее), чтобы избежать потери данных.
целое_число = 123 float_number = 1,23 новое_число = целое_число + плавающее_число # отображаем новое значение и результирующий тип данных print("Значение:",new_number) print("Тип данных:",type(new_number))
Выход
Значение: 124,23 Тип данных:
В приведенном выше примере мы создали две переменные: integer_number и float_number типа int
и float
соответственно.
Затем мы добавили эти две переменные и сохранили результат в new_number .
Как мы видим, new_number имеет значение 124,23 и имеет число с плавающей точкой 9.0006 тип данных.
Это связано с тем, что Python всегда преобразует меньшие типы данных в большие, чтобы избежать потери данных.
Примечание:
- Мы получим
TypeError
, если попытаемся добавитьstr
иint
. Например,'12' + 23
. Python не может использовать неявное преобразование в таких условиях. - В Python есть решение для подобных ситуаций, известное как явное преобразование.
Явное преобразование типов
При явном преобразовании типов пользователи преобразуют тип данных объекта в требуемый тип данных.
Мы используем встроенные функции, такие как int()
, float()
, str()
и т. д. для выполнения явного преобразования типов.
Этот тип преобразования также называется приведением типов, поскольку пользователь приводит (изменяет) тип данных объектов.
Пример 2. Добавление строки и целого числа с использованием явного преобразования
num_string = '12' число_целое = 23 print("Тип данных num_string до приведения типов:",type(num_string)) # явное преобразование типов num_string = целое (num_string) print("Тип данных num_string после приведения типов:",type(num_string)) num_sum = num_integer + num_string печать("Сумма:",num_sum) print("Тип данных num_sum:",type(num_sum))
Вывод
Тип данных num_string до приведения типов:Тип данных num_string после приведения типов: Сумма: 35 Тип данных num_sum: <класс 'int'>
В приведенном выше примере мы создали две переменные: num_string и num_integer со значениями типа str
и int
соответственно. Обратите внимание на код:
num_string = int(num_string)
Здесь мы использовали int()
для выполнения явного преобразования типа num_string в целочисленный тип.
После преобразования num_string в целочисленное значение Python может добавить эти две переменные.
Наконец, мы получили значение num_sum , т.е. 35 и тип данных int
.
Ключевые моменты, которые следует помнить
- Преобразование типов — это преобразование объекта из одного типа данных в другой тип данных.
- Неявное преобразование типов автоматически выполняется интерпретатором Python.
- Python позволяет избежать потери данных при неявном преобразовании типов.
- Явное преобразование типов также называется преобразованием типов, типы данных объектов преобразуются с использованием предопределенных функций пользователем.
- При приведении типов может произойти потеря данных, поскольку мы привязываем объект к определенному типу данных.
Содержание
Что такое преобразование типов в Python
Метод преобразования типов данных Python называется преобразованием типа. Мы можем преобразовывать объекты строкового типа в числовое значение, преобразовывать их в различные типы контейнеров и т. д. В основном Python предоставляет два типа методов преобразования: неявный тип преобразования и явный тип преобразования. Чтобы освоить аргументы командной строки sys.argv в Python, нажмите здесь.
Ознакомьтесь с Self in Python , нажав здесь!
Неявное преобразование типов в Python:
В Python преобразование типа данных называется неявным преобразованием типа данных, если оно происходит во время компиляции или во время выполнения. Python управляет преобразованием неявного типа данных, поэтому мы не можем напрямую преобразовывать тип данных в другой тип данных.
Неявное приведение типов означает преобразование без потери первоначального значения форм данных. Эта форма приведения типов важна, если вы хотите настроить данные без изменения важности значений, хранящихся в переменной.
Преобразование неявного типа происходит автоматически, если значение копируется в совместимый с ним тип. Во время преобразования должны соблюдаться строгие правила преобразования форм. Если операнды имеют два разных типа данных, то операнд с более низким типом данных будет автоматически преобразован в более высокий тип данных.
Давайте добавим две переменные Python с двумя типами данных, сохраним результат в переменной и посмотрим, преобразует ли компилятор Python результирующий тип данных переменной.
значение1 = 10 значение2 = 10,5 сумма = значение1 + значение2 печать (сумма) print (type (sum)) #type() используется для отображения типа данных переменной
Вывод:
20,5
В приведенном выше примере мы взяли и добавили две переменные с целочисленными данными и данными с плавающей запятой. Кроме того, мы объявили и сохранили результат добавленной переменной под названием «сумма». Проверяя тип данных переменной суммы, компилятор Python автоматически преобразует тип данных переменной суммы в тип данных с плавающей запятой. Это называется преобразованием неявного типа.
Преобразование переменной суммы в тип данных с плавающей запятой объясняется тем, что если бы компилятор преобразовал ее в целочисленный тип данных, дробную часть пришлось бы опустить, и произошла бы потеря данных. Таким образом, Python превращает меньшие типы данных в более крупные, чтобы избежать потери данных.
В некоторых случаях Python не может использовать неявное преобразование, и в игру вступает явное преобразование формы.
Явное преобразование типов в Python:
Пользователи преобразуют тип данных объекта в тип данных, необходимый для явного преобразования типов. Чтобы выполнить явное преобразование типов, мы используем предопределенные функции, такие как int(), float(), str().
Эта форма преобразования также называется приведением типов, поскольку пользователь приводит (изменяет) тип данных объекта.
Преобразование явного типа происходит, когда программист четко и явно указывает программу. Существует несколько встроенных функций Python для явного преобразования формы.
Синтаксис:
(требуемый_тип_данных)(выражение) Пример: значение1 = 100 значение2 = «300» результат1 = значение1 + значение2 значение2 = целое (значение2) результат2 = значение1 + значение2 печать(результат2)
Вывод:
Трассировка (последний последний вызов): Файл «», строка 1, в TypeError: неподдерживаемые типы операндов для +: ‘int’ и ‘str’ 400
Значение переменной1 — это номер типа данных, а значение переменной2 — строка типа данных. Если эти две записи вставляются, а значение сохраняется в переменной с именем result1, возникает ошибка TypeError, как видно из выходных данных. Таким образом, мы должны использовать явное приведение типов для выполнения этой операции.
Мы преобразовали переменную value2 в int, а затем вставили переменные value1 и value2. Сумма сохраняется в переменной result2, а на выходе отображается 400.
int(a, base):
Эта функция int (a, base) преобразует любой тип данных в целое число. Это метод преобразования числовой строки в заданном базовом значении в десятичное значение. «База» определяет базу, в которую преобразуется строка, если тип данных является строкой. По умолчанию для параметра «База» установлено значение 10.
Пример:
попробуйте: а = «10010» #stringconvertingtointbase2 с = целое (а, 2) print('строка преобразована в базу2:',с) #stringconvertingtointbase10 с = целое (а) print('строка преобразована в базу10:',c) кромеTypeErrorastypeError: print(typeError)
Вывод:
строка, преобразованная в базу данных2: 18 stringconvertedtointbase10: 10010
float():
Метод float() возвращает число с плавающей запятой из числа или строки.
- Синтаксис:
- float(a)
- Типы аргументов, которые метод принимает:
- Число: может быть либо целым числом, либо числом с плавающей запятой.
- Строка:
Должен иметь какой-либо тип числа.
- Метод игнорирует пробелы слева и справа и новые строки.
- Можно использовать математические операторы.
- Может включать NaN, Infinity или Inf (в любых случаях)
Значения, которые могут быть возвращены функцией float() в соответствии с переданным оператором: прошедший. Пример: Вывод: переданный аргумент. Другими словами, функция ord() возвращает целое число точки Unicode символа в случае Unicode или значение байта в случае 8-битного аргумента. Пример 1: Мы находим значения кодовой точки Unicode для целого числа, символа и специального символа. Первые 128 точек Unicode аналогичны точкам ASCII, что означает, что точки Unicode совпадают со значениями ASCII переданных строк длины 1. Вывод: Пример 2: Возникает ошибка, когда длина строки не равна 1 Функция hex() — это одна из встроенных функций Python3, используемая для преобразования целого числа в подходящую шестнадцатеричную форму для числа целого числа. Synta x: Функция hex() преобразует и возвращает целое число в виде строки в соответствующее шестнадцатеричное число. Возвращаемая шестнадцатеричная строка начинается с префикса 0x, что означает, что она шестнадцатеричная. Пример 2: Выходные данные: Пример 2: Передача типов, отличных от целых, в метод hex() вызывает ошибку. Вывод: oct() — это один из встроенных методов Python3. Метод oct() является целым числом и возвращает его восьмеричное представление в строковом формате. Синтаксис: Пример: Вывод: Эта функция используется для преобразования типа данных в кортеж. Кортеж создается путем помещения всех элементов (элементов), разделенных запятыми, в круглые скобки (). Скобки необязательны, но их использование — отличная практика. Эта функция принимает один итерируемый параметр (необязательно). Это итерируемый объект (список, диапазон и т. д.). Соответствующий кортеж генерируется, если передается итерируемый объект. Если вы не перемещаете итерируемый объект, создаются пустые кортежи. Синтаксис: Эта функция принимает один повторяемый параметр (необязательно). Это повторяемый объект (список, диапазон и т.д.). Соответствующий кортеж формируется при перемещении итерируемого объекта. Если вы не перемещаете итерируемый объект, вы создаете пустой кортеж. Вывод: синтаксис: Пример: Вывод: Эта функция преобразует все типы данных в тип списка. Конструктор list() возвращает список. Вывод: Эта функция используется для преобразования кортежа порядка (ключ, значение) в словарь. Пример: Вывод: Эта функция используется для преобразования значения (целого числа или числа с плавающей запятой) в строку. Пример: Вывод: Когда заданы действительная и мнимая части, метод complex() возвращает комплексное число или преобразует строку в комплексное число. Complex() обычно принимает два параметра: Если эта форма является первым передаваемым параметром, она будет интерпретироваться как комплексное число. В этом случае вы не передаете второй параметр. Пример: Вывод: Метод chr() возвращает символ (строку) из целого числа (представляет кодовую точку Unicode символа). попробуйте:
а = «10010»
#stringconvertingtofloat
с = с плавающей запятой (а)
print('stringconvertedtofloat:',c)
кромеTypeErrorastypeError:
print(typeError)
stringconvertedtofloat: 10010. 0
ord():
Синтаксис:
ord("string")
# кодовая точка unicode целого числа
print("Значение ASCII 9 равно",ord('9'))
# кодовая точка юникода в алфавите
print("Значение ASCII для B равно",ord('B'))
# кодовая точка unicode специального символа
print("Значение ASCII ! равно",ord('!'))
Значение ASCII 9 равно 57
Значение ASCII B равно 66.
Значение ASCII ! is 33
value1 =ord('AB')
значениепечать(значение1)
Ошибка выполнения:
Traceback (последний последний вызов):
Файл «/home/f988dfe667cdc9a8e5658464c87ccd18. py», строка 6, в
значение1 = порядок('AB')
TypeError: ord() ожидал символ, но строка длиной 2 нашла
hex():
hex(x)
попробуйте:
а=5
c=hex(a)#преобразует5вшестнадцатеричноезначение
печать («шестнадцатеричное значение 5:», с)
кромеTypeErrorastypeError:
print(typeError)
шестнадцатеричное значение5: 0x5
попытка:
а = ‘4’
c=hex(a)#преобразует4вшестнадцатеричноезначение
печать («шестнадцатеричное значение 4:», с)
кромеTypeErrorastypeError:
print(typeError)
Объект ‘str’ не может быть интерпретирован как целое число
oct():
окт(х)
print("Восьмеричное представление 23 равно "+oct(x))
print("Восьмеричное представление"" ascii-значения 'z' равно "+oct(ord('z')))
# Двоичное представление числа # можно передать как параметр
# Для 23 двоичный код равен 0b10111.
print("Восьмеричное представление двоичного кода"" числа 23 равно "+oct(0b10111))
# Для 23 шестнадцатеричное число равно 0x17.
print("Восьмеричное представление двоичного кода"" числа 23 равно "+oct(0x17))
Восьмеричное представление числа 23 равно 0o27.
Восьмеричное представление значения ascii 'z' равно 0o172.
Восьмеричное представление двоичного числа 23 равно 0o27.
Восьмеричное представление двоичного числа 23: 0o27
tuple():
tuple(iterable)
# если параметр не передан
кортеж1 =кортеж()
печать (кортеж1)
# когда передается итерируемый объект (например, список)
список1=[ 1, 2, 3, 4]
кортеж2 = кортеж (список1)
печать (кортеж2)
# когда передается итерируемый объект (например, словарь)
dict={ 1: 'один', 2: 'два'}
кортеж3 =кортеж(дикт)
печать (кортеж3)
# когда передается итерируемый объект (например, строка)
строка = "Индия"
кортеж4 = кортеж (строка)
print(tuple4)
()
(1, 2, 3, 4)
(1, 2)
('и', 'н', 'д', 'и', 'а')
набор():
Метод set() используется для преобразования всех итерируемых элементов в повторяемую последовательность, обычно называемую Set.
set(iterable)
# список инициализации
lis1 =[ 3, 4, 1, 4, 5]
# инициализация кортежа
tup1 =(3, 4, 1, 4, 5)
# Печать итераций перед преобразованием
print("Список перед преобразованием : "+str(lis1))
print("Кортеж перед преобразованием : "+str(tup1))
# Итерации после преобразования отличаются друг от друга, а элементы
print("Список после преобразования : "+str(set(lis1)))
print("Кортеж после преобразования: "+str(set(tup1)))
Список до преобразования: [3, 4, 1, 4, 5]
Кортеж перед преобразованием: (3, 4, 1, 4, 5)
Список после преобразования: {1, 3, 4, 5}
Кортеж после преобразования: {1, 3, 4, 5}
list():
# пустой список
распечатать (список ())
# строка гласных
vowel_string = 'аиоу'
печать (список (vowel_string))
# кортеж гласных
vowel_tuple = ('а', 'е', 'и', 'о', 'у')
печать (список (vowel_tuple))
# список гласных
vowel_list = ['а', 'е', 'и', 'о', 'у']
print(list(vowel_list))
[]
['а', 'е', 'и', 'о', 'у']
['а', 'е', 'и', 'о', 'у']
['a', 'e', 'i', 'o', 'u']
dict():
# аргумент ключевого слова не передан
числа1 = dict([('x', 5), ('y', -5)])
печать('числа1 =',числа1)
# аргумент ключевого слова также передается
числа2 = dict([('x', 5), ('y', -5)], z=8)
печать('числа2 =',числа2)
# zip() создает итерируемый объект в Python 3
числа3 = dict(dict(zip(['x', 'y', 'z'], [1, 2, 3])))
print('numbers3 =',numbers3)
числа1 = {'y': -5, 'x': 5}
числа2 = {'z': 8, 'y': -5, 'x': 5}
числа3 = {'z': 3, 'y': 2, 'x': 1}
str():
число = 100
с = ул (число)
печать (ы, тип (ы))
число = 100,1
с = ул (число)
print(s, type(s))
100
complex(real,imag)
z = комплекс (2, -3)
печать (г)
г = комплекс (1)
печать (г)
z = сложный()
печать (г)
z = комплекс('5-9к')
print(z)
(2-3j)
(1+0j)
0j
(5-9j)
chr(number)