TypeError и ValueError в Python: чем отличаются

Python Автор: Среда и версия: CPython 3.14.7; исполняемые блоки — Pyodide 3.14.0 прямо на странице
содержание

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

TypeError — объект не того типа. Операция к такому типу неприменима в принципе, и никакое значение этого типа не подойдёт.

ValueError — тип верный, а значение не годится. Операция применима, но конкретно с этими данными выполниться не может.

Python / 01

Тип не подходит или значение не годится

Тип не подходит или значение не годится01 TypeError int(None) Операция не принимает такой тип. Проверь источник аргумента. 02 ValueError int("нет") Строка допустима по типу, но не содержит число. Проверь значение.01TypeErrorint(None)Операция не принимает такой тип. Проверьисточник аргумента.02ValueErrorint("нет")Строка допустима по типу, но не содержитчисло. Проверь значение.
Порядок проверок и определяет, какое исключение прилетит. Отсюда практический вывод: TypeError обычно значит, что данные пришли не оттуда, а ValueError — что источник верный, но содержимое надо проверять.

Одна функция, три аргумента, два разных исключения

for value in ["10", "десять", None]:
    try:
        print(f"int({value!r}) = {int(value)}")
    except (TypeError, ValueError) as exc:
        print(f"int({value!r}) → {type(exc).__name__}: {exc}")
int('10') = 10
int('десять') → ValueError: invalid literal for int() with base 10: 'десять'
int(None) → TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType'

"десять" — строка, то есть тип для int() подходящий; не годится содержимое, отсюда ValueError. None вообще не тот тип — TypeError. Строка "10" проходит обе проверки.

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

Правило предсказывает: распаковка

Одна и та же операция, три разных неудачи:

def three_from_two():
    a, b, c = [1, 2]


def two_from_three():
    a, b = [1, 2, 3]


def two_from_int():
    a, b = 5


cases = [("a, b, c = [1, 2]", three_from_two),
         ("a, b = [1, 2, 3]", two_from_three),
         ("a, b = 5", two_from_int)]

for label, fn in cases:
    try:
        fn()
    except (TypeError, ValueError) as exc:
        print(f"{label:18}{type(exc).__name__}: {exc}")
a, b, c = [1, 2]   → ValueError: not enough values to unpack (expected 3, got 2)
a, b = [1, 2, 3]   → ValueError: too many values to unpack (expected 2, got 3)
a, b = 5           → TypeError: cannot unpack non-iterable int object

Список из двух элементов там, где ждут три, — правильный тип с негодной длиной, значит ValueError. Число вместо последовательности — не тот тип, значит TypeError. Правило сработало оба раза, ещё до запуска.

Объект не вызывается

Единственное частое сообщение, которое сбивает с толку формулировкой:

prices = {"мышь": 100}
try:
    prices("мышь")
except TypeError as exc:
    print(f"TypeError: {exc}")

total = 5
try:
    total(1)
except TypeError as exc:
    print(f"TypeError: {exc}")
TypeError: 'dict' object is not callable
TypeError: 'int' object is not callable

«Not callable» значит «ты пытаешься вызвать объект, который не поддерживает вызов». Вызываемыми бывают не только функции, но и классы, и экземпляры с __call__. Частые причины ошибки: перепутаны круглые скобки с квадратными (prices("мышь") вместо prices["мышь"]) или имя функции затёрто значением — где-то выше по коду total = 5 заменил функцию total.

Таблица частых сообщений

Каждое разобрано подробно в своей статье — тип ошибки говорит, что чинить, а ссылка ведёт туда, где показано как.

СообщениеЧто произошлоПодробный разбор
invalid literal for int() with base 10строка не похожа на числопреобразование типов
can only concatenate str (not "int") to strсложение строки с числомпреобразование типов
unsupported operand type(s) for +операция неприменима к этой паре типовдата и время
'NoneType' object is not subscriptableобращение по ключу к Noneсловари
'int' object is not iterableцикл по тому, что не последовательностьциклы
takes N positional arguments but M were givenневерное число аргументовargs и kwargs
unhashable type: 'list'список как ключ словаряизменяемые и неизменяемые
substring not foundindex() не нашёл подстрокуметоды строк
list.remove(x): x not in listудаление отсутствующего элементаметоды списков
'NoneType' object has no attributeвызов метода у NoneAttributeError

Как ловить

Ловить эти два исключения вместе имеет смысл там, где данные приходят извне и любая беда с ними обрабатывается одинаково:

def parse_age(raw):
    try:
        return int(raw)
    except (TypeError, ValueError):
        return None


print(parse_age("42"), parse_age("сорок два"), parse_age(None))
42 None None

Порознь — когда реакция разная: на ValueError осмысленно попросить пользователя ввести значение заново, а TypeError обычно означает изъян в коде, и глушить его молча значит спрятать баг. Механика самого try/except, включая else, finally и свои исключения, разобрана в отдельной статье.

Частые вопросы

Чем TypeError отличается от ValueError

TypeError — объект не того типа, операция к нему неприменима вообще. ValueError — тип подходит, но конкретное значение обработать нельзя. int(None) даёт первое, int("десять") — второе.

Что значит object is not callable

Что после объекта стоят круглые скобки, но он не поддерживает вызов. Чаще всего это перепутанные скобки — prices("ключ") вместо prices["ключ"] — или переменная, затёршая функцию с тем же именем.

Почему распаковка даёт то ValueError, то TypeError

Потому что причины разные. Неверное количество элементов — правильный тип с негодным значением, отсюда ValueError. Объект, по которому нельзя пройти вовсе, — неподходящий тип, отсюда TypeError.

Стоит ли ловить TypeError

Обычно нет. ValueError приходит от чужих данных, и его обрабатывают. TypeError почти всегда означает ошибку в собственном коде, и пусть он падает громко — так его чинят, а не прячут.

Как узнать, где именно упало

Смотри последнюю строку трассировки — там тип и сообщение, а строкой выше файл и номер строки. Если кадров много, нужен первый снизу, который принадлежит твоему коду, а не библиотеке.

Где потренироваться

Блоки на этой странице запускаются здесь же — подставь свои значения в int() и посмотри, какое из двух исключений прилетит; правило проверяется за минуту. На живых задачах разбор пользовательского ввода встречается в проверке пароля.

Источники