Как работают преобразования типов
Преобразование типов в Python: базовый подход
Основной путь в Python связан с вызовом типа как функции. Конструкторы int(), float(), str(), bool(), list(), tuple(), set(), dict(), bytes() создают объект нового типа на основе переданного значения. Если преобразование невозможно, интерпретатор сообщает об ошибке.
# Пример базовых преобразований
age = int('42')
price = float('19.95')
text = str(100)
flag = bool(0)
items = list((1, 2, 3))
coords = tuple([4, 5])
user = dict([('name', 'Anna'), ('age', 30)])
unique = set([1, 2, 2, 3])
data = bytes('привет', encoding='utf-8')
print(age)
print(price)
print(text)
print(flag)
print(items)
print(coords)
print(user)
print(unique)
print(data.decode('utf-8'))
Python список цифр в число (преобразование списка цифр в число в python)
42
19.95
100
False
[1, 2, 3]
(4, 5)
{'name': 'Anna', 'age': 30}
{1, 2, 3}
привет
Python преобразование типов (преобразование типов в python)
Каждый шаг создаёт новый объект. Целые числа, строки и кортежи неизменяемы, поэтому исходное значение остаётся прежним. Списки, словари и множества могут быть созданы из других коллекций. Для строк в bytes явно указывается кодировка, потому что байты и текст относятся к разным уровням представления данных.
Ошибки возникают при несовместимых типах: int('12.5') даёт ValueError, int(None) даёт TypeError, dict([1, 2]) даёт TypeError, list(10) даёт TypeError. Причина в том, что Python не выполняет неявное приведение там, где возможна потеря данных или неоднозначность. Проверка isinstance() и конструкция try/except дают предсказуемое поведение.
Как преобразовать число в строку с нужной точностью?
Функция str() даёт краткое представление. Форматные строки и format() управляют округлением, разделителями и выравниванием. Такой подход применяется для отчётов, логов и пользовательского вывода.
value = 1234.56789
print(str(value))
print(format(value, '.2f'))
print(f'{value:,.2f}')
print(f'{255:08b}')
print(f'{42:x}')
Python функции преобразования (функции преобразования в python)
1234.56789 1234.57 1,234.57 11111111 2a
str() не меняет число. format() возвращает новую строку. f-строка вычисляет выражение и подставляет результат. Округление в format() выполняется по правилам двоичного представления float, поэтому Decimal подходит для денежных расчётов.
Типичная ошибка: ожидание, что str(0.1 + 0.2) даст '0.3'. На практике появляется '0.30000000000000004'. Для финансовых значений применяется decimal.Decimal или округление на этапе вывода.
Как преобразовать строку в число при неизвестном формате?
Базовые int() и float() принимают строки с пробелами и знаками. Для запятых, валют и процентов требуется предварительная очистка. Decimal сохраняет десятичную точность, Fraction работает с рациональными числами.
from decimal import Decimal
from fractions import Fraction
print(int(' -15 '))
print(float('1_000.5'))
print(Decimal('19.99'))
print(Fraction('3/4'))
raw = '1 234,50 руб.'
clean = raw.replace(' ', '').replace(',', '.').replace('руб.', '')
print(float(clean))
-15 1000.5 19.99 3/4 1234.5
int() не принимает десятичную точку. float() принимает точки и экспоненту. Decimal получает строку и не проходит через двоичное округление. Очистка строки зависит от локали и формата источника.
Ошибка ValueError появляется при пустой строке, лишних символах или неверном разделителе. Для пользовательского ввода помогает регулярное выражение и замена разделителей. Нельзя считать, что запятая всегда десятичный разделитель: в части локалей она разделяет тысячи.
Как связаны bool, int и float?
bool является подклассом int. False равен 0, True равен 1. Функция bool() использует протокол истинности: пустые коллекции, 0, None и пустые строки дают False.
print(True + True)
print(int(True), int(False))
print(bool(0), bool(0.0), bool(''), bool([]), bool({}))
print(bool('0'), bool([0]), bool(-1))
print(1 == True, 0 == False)
2 1 0 False False False False False True True True True True
Арифметика с bool возможна, но ухудшает читаемость. Явное int(flag) или float(flag) показывает намерение. Проверка if value: использует bool(value) неявно.
Опасность: строка 'False' не равна False. bool('False') даёт True, потому что строка непустая. Для разбора текстовых флагов нужна отдельная логика сравнения с 'true', 'false', '1', '0'.
Как преобразовать коллекции между list, tuple, set и dict?
Конструкторы list(), tuple(), set() принимают любой итерируемый объект. dict() ожидает пары ключ-значение или именованные аргументы. Преобразование создаёт новый контейнер, но вложенные объекты не копируются глубоко.
source = [('a', 1), ('b', 2)]
mapping = dict(source)
print(mapping)
print(list(mapping))
print(tuple(mapping))
print(set([1, 2, 2, 3]))
print(dict(a=1, b=2))
print(dict.fromkeys(['x', 'y'], 0))
{'a': 1, 'b': 2}
['a', 'b']
('a', 'b')
{1, 2, 3}
{'a': 1, 'b': 2}
{'x': 0, 'y': 0}
set() удаляет дубликаты и меняет порядок. list(mapping) даёт ключи. dict() из списка пар сохраняет порядок вставки. dict.fromkeys() создаёт словарь с одинаковым значением по умолчанию.
Ошибка: dict([1, 2, 3]) вызывает TypeError, потому что элементы не являются парами. Для вложенных списков подходит dict() только при длине элемента 2. Изменяемые ключи, например list, недопустимы в dict и set.
Как преобразовать str в bytes и обратно?
Текст и байты разделены. str.encode() возвращает bytes, bytes.decode() возвращает str. Кодировка по умолчанию utf-8, но её лучше указывать явно. Обработка ошибок задаётся параметром errors.
text = 'Привет, мир!'
data = text.encode('utf-8')
print(data.hex())
print(data.decode('utf-8'))
broken = bytes([255, 254])
print(broken.decode('utf-8', errors='replace'))
d09fd180d0b8d0b2d0b5d1822c20d0bcd0b8d18021 Привет, мир! ��
hex() показывает байты без escape-последовательностей. errors='replace' заменяет неподходящие байты. Для неизвестной кодировки применяется charset-normalizer или попытки декодирования с несколькими вариантами.
Ошибка UnicodeDecodeError появляется при чтении байтов в неверной кодировке. Ошибка UnicodeEncodeError возникает, если текст содержит символы, отсутствующие в целевой кодировке, например cp1251. Параметр errors='ignore' скрывает проблему, поэтому его применение требует обоснования.
Как сделать безопасное преобразование с обработкой ошибок?
Для внешних данных применяется try/except. Функция возвращает значение или значение по умолчанию. Такой приём используется в парсингах, API и файлах конфигурации.
def to_int(value, default=None):
try:
return int(value)
except (TypeError, ValueError):
return default
print(to_int('42'))
print(to_int('4.2'))
print(to_int(None, 0))
print(to_int('abc', -1))
42 None 0 -1
Перехват конкретных исключений не скрывает ошибки программирования. Значение по умолчанию должно быть отделено от валидного результата. Для сложных схем подходит pydantic, dataclasses с валидацией или typing в сочетании с проверками.
Ловушка: except Exception скрывает опечатки и системные ошибки. Другая проблема: возврат None для отсутствия значения может конфликтовать с реальным None. В таких случаях применяется sentinel-объект или исключение.
Расширенные примеры преобразований в Python
Примеры показывают взаимодействие с протоколами языка, стандартной библиотекой и внешними форматами. Каждый блок содержит код и результат.
Пользовательские классы и специальные методы
Класс может определять преобразование через __int__, __float__, __str__, __bool__ и __index__. Вызов int(obj) ищет __int__ или __index__, float(obj) ищет __float__, str(obj) использует __str__, bool(obj) использует __bool__ или __len__.
class Temperature:
def __init__(self, celsius):
self.celsius = celsius
def __int__(self):
return int(self.celsius)
def __float__(self):
return float(self.celsius)
def __str__(self):
return f'{self.celsius} C'
def __bool__(self):
return self.celsius != 0
t = Temperature(21.7)
print(int(t))
print(float(t))
print(str(t))
print(bool(t))
print(bool(Temperature(0)))
21 21.7 21.7 C True False
Ошибка возникает, если __int__ возвращает не int, а, например, float. Python требует точный тип. Для среза и hex() нужен __index__, а не __int__.
__index__ для индексов и систем счисления
class Index:
def __index__(self):
return 3
idx = Index()
items = [10, 20, 30, 40]
print(items[idx])
print(hex(idx))
print(bin(idx))
print(oct(idx))
40 0x3 0b11 0o3
Decimal и Fraction
Decimal хранит десятичные дроби без двоичного шума. Fraction строит рациональное число из строки, float или Decimal.
from decimal import Decimal, ROUND_HALF_UP
from fractions import Fraction
d = Decimal('2.675')
print(d.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP))
print(int(d))
print(float(d))
print(Decimal.from_float(0.1))
print(Fraction(0.5))
print(Fraction('0.25'))
print(Fraction(Decimal('0.1')))
2.68 2 2.675 0.1000000000000000055511151231257827021181583404541015625 1/2 1/4 1/10
Decimal.from_float показывает точное двоичное представление. Для денег используется Decimal('0.1'), а не Decimal(0.1). Иначе в число попадает двоичная погрешность.
Даты и временные метки
from datetime import datetime, timezone
dt = datetime(2024, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
ts = dt.timestamp()
print(ts)
print(datetime.fromtimestamp(ts, tz=timezone.utc))
print(dt.isoformat())
1704164645.0 2024-01-02 03:04:05+00:00 2024-01-02T03:04:05+00:00
JSON и ручное приведение полей
import json
raw = {'id': '10', 'price': '19.99', 'active': 'true'}
data = dict(raw)
data['id'] = int(data['id'])
data['price'] = float(data['price'])
data['active'] = data['active'] == 'true'
print(data)
print(json.dumps(data))
print(type(data['id']))
print(type(data['price']))
print(type(data['active']))
{'id': 10, 'price': 19.99, 'active': True}
{"id": 10, "price": 19.99, "active": true}
json.loads уже создаёт int, float, bool. Если поле пришло строкой, тип остаётся str. Автоматическая замена типов по значению опасна: строка '0' может быть идентификатором, а не числом.
CSV и преобразование строк таблицы
import csv
rows = list(csv.DictReader(['id,price', '1,10.5', '2,20.0']))
converted = [
{'id': int(row['id']), 'price': float(row['price'])}
for row in rows
]
print(converted)
[{'id': 1, 'price': 10.5}, {'id': 2, 'price': 20.0}]
Байты, struct и целые числа
import struct
number = 123456
packed = struct.pack('!i', number)
print(packed.hex())
print(struct.unpack('!i', packed)[0])
print(int.from_bytes(packed, 'big'))
print(number.to_bytes(4, 'big').hex())
0001e240 123456 123456 0001e240
Base64 и кодировки
import base64
text = 'Привет'
raw = text.encode('utf-8')
encoded = base64.b64encode(raw)
print(encoded)
print(base64.b64decode(encoded).decode('utf-8'))
b'0J/RgNC40LLQtdGC' Привет
ast.literal_eval для безопасного разбора простых литералов
import ast
print(ast.literal_eval('123'))
print(ast.literal_eval('1.5'))
print(ast.literal_eval('[1, 2, 3]'))
print(ast.literal_eval("{'a': 1, 'b': 2}"))
print(ast.literal_eval('True'))
123
1.5
[1, 2, 3]
{'a': 1, 'b': 2}
True
ast.literal_eval не выполняет произвольный код, но принимает только литералы. Выражения, имена переменных и вызовы функций вызывают ValueError. Для сложных схем применяется json.loads или специализированный парсер.
Преобразование через map и генераторы
values = ['1', '2', '3.5', '4']
ints = list(map(int, values[:2]))
floats = [float(x) for x in values[2:]]
print(ints)
print(floats)
print(sum(ints) + sum(floats))
[1, 2] [3.5, 4.0] 10.5
Собственный безопасный конвертер
def convert(value, target, default=None):
try:
if target is bool:
if isinstance(value, str):
return value.strip().lower() in {'1', 'true', 'yes', 'on'}
return bool(value)
return target(value)
except (TypeError, ValueError):
return default
print(convert('42', int))
print(convert('3.14', float))
print(convert('true', bool))
print(convert('no', bool))
print(convert('abc', int, 0))
42 3.14 True False 0
Для bool нельзя применять bool('False'), потому что непустая строка истинна. Отдельная проверка текстовых значений устраняет эту ловушку. Значение по умолчанию стоит выбирать так, чтобы оно отличалось от валидных данных.
Преобразование типов в аннотациях и typing
from typing import Union
def parse_port(value: Union[str, int]) -> int:
port = int(value)
if not 1 <= port <= 65535:
raise ValueError('port out of range')
return port
print(parse_port('8080'))
try:
print(parse_port(0))
except ValueError as error:
print(error)
8080 port out of range
Аннотации не выполняют преобразование во время работы. Они служат документацией и проверяются инструментами вроде mypy. Фактическое приведение выполняет код внутри функции.