Вопрос-Ответ

I'm getting a TypeError. How do I fix it?

Я получаю ошибку типа. Как мне это исправить?

Обычно я получаю неперехваченные исключения (ошибки) из моего кода Python, которые описываются как TypeErrors. После значительных экспериментов и исследований я смог собрать следующие примеры (и незначительные вариации):

TypeError: func() takes 0 positional arguments but 1 was given
TypeError: func() takes from 1 to 2 positional arguments but 3 were given
TypeError: func() got an unexpected keyword argument 'arg'
TypeError: func() missing 1 required positional argument: 'arg'
TypeError: func() missing 1 required keyword-only argument: 'arg'
TypeError: func() got multiple values for argument 'arg'
TypeError: MyClass() takes no arguments
TypeError: unsupported operand type(s) for +: 'int' and 'str'
TypeError: can only concatenate str (not "int") to str
TypeError: '>' not supported between instances of 'int' and 'str'
TypeError: can't multiply sequence by non-int of type 'float'
TypeError: string indices must be integers
TypeError: %d format: a number is required, not str
TypeError: not all arguments converted during string formatting
TypeError: list indices must be integers or slices, not str
TypeError: int() argument must be a string, a bytes-like object or a number, not 'list'
TypeError: a bytes-like object is required, not 'str'
TypeError: bad operand type for abs(): 'str'
TypeError: descriptor 'to_bytes' for 'int' objects doesn't apply to a 'str' object
TypeError: 'int' object is not iterable
TypeError: cannot unpack non-iterable int object
TypeError: 'int' object is not callable
TypeError: 'int' object is not subscriptable

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

Что такое TypeError? Что означают подобные сообщения? Как я могу понять и устранить проблему?


Если ваш вопрос был закрыт как дубликат этого, пожалуйста, внимательно прочитайте и следуйте приведенным здесь советам, а также попробуйте отладить код и исследовать любую оставшуюся проблему, прежде чем задавать снова. Stack Overflow - это не служба отладки.

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

Переведено автоматически
Ответ 1

Что такое TypeError?

Это означает именно то, на что похоже: существует ошибка, Error которая вызвана Type одним или несколькими значениями в коде.

... но что такое "тип"?

В программе на Python каждый объект имеет тип. Под "объектом" (эквивалентно в Python "значению") мы подразумеваем нечто, чему может быть присвоено имя в исходном коде. Большинство имен представляют собой простые переменные: если мы пишем x = 1, то 1 это объект, у него есть имя x, и его тип int - у самого типа есть имя.

"Тип" означает более или менее то, как это звучит: он сообщает вам, что это за вещь что-то еще. 1, 2 и 3 все это целые числа; они имеют один и тот же тип, int. Вы можете думать об этом как о представлении концепции целого числа.

Не у каждого типа есть встроенное имя. Например, функции являются объектами (большинство других языков так не работают!), И у них есть тип, но мы не можем напрямую ссылаться на этот тип по имени в нашем коде.

Однако каждый тип действительно имеет представление в виде объекта, независимо от того, назван он или нет. Вы можете использовать встроенный type, чтобы получить такой "объект типа":

>>> type(1) # the result from this...
<class 'int'>
>>> int # is the same:
<class 'int'>
>>> type(int) # We can look a bit deeper:
<class 'type'>
>>> def func():
... pass
>>> type(func) # and get types that aren't named:
<class 'function'>
>>> type(type) # and there's this special case:
<class 'type'>

Примечательно, что тип type является type самим собой.

Вы можете заметить, что Python (3.x) отображает объекты этого типа со словом class. Это полезное напоминание: когда вы создаете class, вы определяете новый тип данных. Это цель классов.

Что означают подобные сообщения?

Мы можем разбить примеры на несколько категорий:

TypeError: func() takes 0 positional arguments but 1 was given
TypeError: func() takes from 1 to 2 positional arguments but 3 were given
TypeError: func() got an unexpected keyword argument 'arg'
TypeError: func() missing 1 required positional argument: 'arg'
TypeError: func() missing 1 required keyword-only argument: 'arg'
TypeError: func() got multiple values for argument 'arg'
TypeError: MyClass() takes no arguments

Эти исключения сообщают вам, что аргументы (то, что вы помещаете между ()) для вызова func (или создания экземпляра MyClass) неверны. Либо их слишком много, недостаточно, либо они неправильно помечены.

По общему признанию, это немного сбивает с толку. Мы пытаемся вызвать функцию, и то, что мы вызываем, является функцией - так что тип действительно совпадает. Выявленная проблема связана с количеством аргументов. Однако Python сообщает об этом как TypeError, а не как ValueError. Это может быть сделано для того, чтобы выглядеть более знакомым программистам из других языков, таких как C ++, где "типы" проверяются во время компиляции и могут быть очень сложными - такими, что функции, которые принимают разные типы или количество аргументов, сами считаются имеющими разные типы.

TypeError: unsupported operand type(s) for +: 'int' and 'str'
TypeError: can only concatenate str (not "int") to str
TypeError: '>' not supported between instances of 'int' and 'str'
TypeError: can't multiply sequence by non-int of type 'float'
TypeError: string indices must be integers

Эти исключения говорят вам, что левая и правая части оператора (символ типа + or > или ^, используемый для вычисления результата) не имеют смысла. Например, при попытке разделить или вычесть строки, или повторить строку нецелое число раз, или (в 3.x) сравнить строки с числами. В качестве особого случая вы можете использовать + между двумя строками (или списками, или кортежами), но это не "добавляет" их в математическом смысле. Если вы попытаетесь использовать + между целым числом и строкой, сообщение об ошибке будет отличаться в зависимости от порядка.

TypeError: %d format: a number is required, not str
TypeError: not all arguments converted during string formatting

Это немного сложно. Оператор % используется для получения модуля (остатка при делении чисел), но его также можно использовать для форматирования строк путем замены некоторых заполнителей. (Это устаревшая система, которую трудно настроить и имеет странные особые случаи; в новом коде, пожалуйста, используйте f-strings или .format метод.)

Ошибка возникает из-за того, что заполнители в строке с левой стороны не совпадают с тем, что находится с правой стороны. Во втором случае, вероятно, вы действительно хотели вычислить модуль, поэтому в левой части должно быть число (скорее всего, целое число). Спорно, должны ли они быть ValueErrors вместо этого, поскольку может быть, что содержимое строки неверно. Однако Python не может читать ваши мысли.

TypeError: list indices must be integers or slices, not str

Это также проблема с оператором, на этот раз с [] оператором (используется для индексации в список, нарезки списка или поиска ключа в словаре). Строка имеет смысл внутри [], если мы ищем ключ в словаре, который содержит строки в качестве ключей; но мы не можем индексировать ее в список с ее помощью.

TypeError: int() argument must be a string, a bytes-like object or a number, not 'list'
TypeError: a bytes-like object is required, not 'str'
TypeError: bad operand type for abs(): 'str'

Это означает, что во встроенную функцию (или другой вызываемый объект, например, тип) было передано что-то неправильное. Функции, которые вы получаете из библиотеки, могут создавать свои собственные TypeErrors с пользовательскими сообщениями. Сообщение должно быть довольно простым.

TypeError: descriptor 'to_bytes' for 'int' objects doesn't apply to a 'str' object

Это очень необычно, и большинство людей, которые задают этот вопрос, никогда бы с этим не столкнулись (за исключением, может быть, datetime стандартного библиотечного модуля). Это происходит из-за попытки использовать метод, как если бы это была функция, но присваивая ему неправильный тип для self: например, int.to_bytes('1'). Код неверен, потому что '1' это строка, а строки не поддерживаются .to_bytes. Python не преобразует строку в целое число; и он не может выдать AttributeError вместо этого, потому что to_bytes был произведен поиск в классе, а не в строке.

TypeError: 'int' object is not iterable
TypeError: cannot unpack non-iterable int object
TypeError: 'int' object is not callable
TypeError: 'int' object is not subscriptable

Это означает именно то, на что похоже. "итерируемый" означает "способный к повторению"; т. Е. Проверяется неоднократно для получения отдельных значений. Это происходит в for циклах, при понимании и при попытке преобразовать в список и т.д. Вариант сообщения "распаковать" является результатом попытки использовать синтаксис распаковки для неинтерируемого.

"вызываемый" означает "способный быть вызванным"; "вызвать" что-либо - это написать () после этого (возможно, с аргументами между ()). Такой код, как 1('test') не имеет смысла, потому что 1 не является функцией (или типом).

"subscriptable" означает "возможность подписки"; здесь "subscripting" означает либо использование синтаксиса среза (x[1:2:3]), либо индексирование или поиск ключа (x['test']). Мы можем сделать это только с последовательностями (например, lists или strings) и отображениями (например, dict s).

Ответ 2

Как я могу понять и устранить проблему?

Сначала посмотрите на обратную трассировку, чтобы увидеть, где в коде возникает ошибка. Если она находится в библиотеке, вернитесь к тому моменту, когда ваш код использует библиотеку. Затем внимательно прочитайте сообщение об ошибке и сравните его с кодом, чтобы выяснить, что вызывает жалобу. Наконец, хорошенько подумайте: ошибочна ли операция или значения?

Примеры

(TODO)

Некоторые неочевидные вещи

Повторное использование имен

Возможно, вы переназначили имя встроенного вызываемого объекта, например, str or input или list? Вы пытались повторно использовать имя для двух разных вещей (например, функции и некоторых глобальных данных, которые она использует)?

Имена в Python могут относиться только к одному объекту одновременно. Если вы используете, скажем, list в качестве имени переменной, то это также больше не название "абстрактной концепции списка", поэтому вы не можете использовать его для создания дополнительных списков (что включает преобразование других объектов в списки). Если вы создаете глобальную переменную months со списком строк, а затем пишете функцию months, функция заменяет список, и код функции не может найти список. Это может легко произойти случайно при использовании from some_module import * синтаксиса.

Аналогично, если вы попытаетесь создать класс, который использует то же имя для метода, что и для атрибута данных экземпляров, это вызовет ту же проблему. (Есть также сложный частный случай с @staticmethod).

Обработка списков

Иногда люди ожидают, что смогут использовать список, подобный массиву Numpy, и "транслировать" операцию или вызов функции для каждого элемента списка. Это не работает. Вместо этого используйте понимание списка.

Обработка None

Подумайте, нужно ли вам обрабатывать None как особый случай. Но постарайтесь вообще не попадать в такую ситуацию; "особые случаи недостаточно особенные, чтобы нарушать правила", как говорится.

Пытаюсь использовать библиотеку (включая стандартную библиотеку)

Если что-то работает не так, как вы ожидали (например, попытка вычесть datetime.times или сериализовать экземпляр пользовательского класса как JSON) - вместо того, чтобы пытаться рассматривать проблему как вопрос отладки, ищите решения для того, что вы хотите, чтобы эта часть кода выполняла.

Если в ошибке упоминается тип 'str', а вы думали, что это должно быть число

Вы получили это из input функции? Это дает вам str, даже если это выглядит как число. Пожалуйста, посмотрите, как я могу считывать входные данные как числа?.

Если в ошибке упоминается тип 'function' или 'type', тип

Вы забыли вызвать функцию или создать экземпляр класса?


Сообщения об ошибках о неправильных аргументах

В сообщении об ошибке будет указано имя функции; поэтому посмотрите на ту часть строки, которая вызывает эту функцию, и проверьте аргументы. Правильное ли количество позиционных аргументов? Есть ли аргумент ключевого слова, который должен быть предоставлен, но отсутствует? Есть ли аргумент ключевого слова, который не должен предоставляться? Есть ли позиционный аргумент, который также предоставляется ключевым словом?

Если вы пишете метод для класса, не забудьте учесть self. Это необходимо для методов экземпляра. Если вы вызываете метод, имейте в виду, что self будет учитываться как аргумент (как для суммы "required", так и для суммы "given").

Распространенной ошибкой новичков является попытка использовать метод (который не является classmethod) из класса без создания его экземпляра. Вы бы сделали что-то вроде

value = MyClass.method(things)

где вы должны делать что-то вроде

instance = MyCLass()
value = instance.method(things)

который (неясно) передается instance в качестве первого (self) аргумента в method, и things в качестве второго аргумента.

Если вы используете обратный вызов, который принимает аргументы из косвенного источника, проверьте источник.

Если вы пытаетесь создать экземпляр своего собственного класса и получаете TypeError from __init__, убедитесь, что вы действительно написали __init__.

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

Сообщения об ошибках о типах операндов

Убедитесь, что оператор правильный для того, что вы хотите, чтобы код выполнял (например: ^ не возведение в степень; вы хотите **), а затем проверьте типы операндов.

В большинстве случаев будет уместно преобразовать тип, но подумайте хорошенько. Убедитесь, что операция будет иметь смысл с новыми типами. Например, если код является l + 'second', и l является list, который в данный момент содержит ['first'], велика вероятность, что мы не хотим объединять строки, а вместо этого создаем измененный список, который также содержит 'second' в качестве элемента. Итак, на самом деле мы хотели "добавить" еще один список: l + ['second'].

Если string indices must be integers, возможно, индексируемая строка является JSON или чем-то в этом роде, которая уже должна была быть проанализирована для создания словаря (возможно, с вложенными списками и словарями).

Если list indices must be integers or slices, скорее всего, проблема в list, а не в индексе. Если вы ожидали, что list будет a dict, проверьте, содержит ли он a dict, особенно если он содержит ровно один элемент, который является a dict. Затем проверьте, действительно ли это то, dict на что следует обратить внимание. Если да, то решение простое: просто добавьте другой уровень индексации, чтобы использовать его dict в первую очередь. Это обычно происходит при попытке получить данные из проанализированного JSON.

Сообщения об ошибках форматирования строк

Серьезно, вы намеревались выполнять форматирование строк? Если вы действительно хотите отформатировать строку, рассмотрите возможность использования f-strings или .format метода - их проще отлаживать и в них меньше особых случаев. Но, скорее всего, левая часть - это какая-то строка, подобная '1' которая должна была быть преобразована в int (или возможно float) сначала.

Сообщения об ошибках о "дескрипторе"

Сообщение об ошибке Python здесь довольно загадочное - в нем используется терминология, о которой большинству программистов редко, если вообще когда-либо приходится беспокоиться. Но после распознавания ошибку очень легко сопоставить с шаблоном. Будьте особенно осторожны, если экземпляр класса может быть создан без аргументов - пустая пара круглых скобок ()по-прежнему необходима для создания экземпляра класса; в противном случае код ссылается на сам класс. Для использования методов требуется экземпляр.

Пользовательские сообщения об ошибках от встроенных функций

"Неправильный операнд" для "унарного" оператора (например, bad operand type for unary +: 'str') может быть вызван случайной запятой. 'a', + 'b' это не то же самое, что 'a' + 'b'; он пытается использовать + в качестве унарного оператора в 'b' строке, а затем создать кортеж. (Вы знаете, как можно написать, например, -1 чтобы получить отрицательное число? В - существует унарный оператор. Оказывается, вы можете писать аналогичным образом +1; это означает то же самое, что и 1, конечно.)

Особенно, если вам пришлось перенести код с 2.x на 3.x, будьте очень осторожны с различиями между bytes и str типами в 3.x. bytes представляет необработанные данные; str представляет текст. Это принципиально разные и не связанные вещи, и преобразовать из одной в другую можно только с помощью кодировки. В Python 3.x файлы, которые открываются в двоичном режиме (используя 'b' в строке режима), выдают bytes при чтении, и им должно быть предоставлено что-то совместимое с bytes при записи в. str не подходит; вы должны указать кодировку явно. Каноническое решение этой проблемы - "TypeError: требуется объект, подобный байтам, а не 'str'" при обработке содержимого файла в Python 3.

Сообщения об ошибках, когда что-то "не может" использоваться каким-либо образом

Вы хотели использовать это таким образом?

Python не может прочитать ваши намерения. Например, доступ к элементу списка осуществляется с помощью [], а не (). Если в коде вместо этого указано () , это будет интерпретировано как попытка вызвать список, поэтому в сообщении об ошибке будет указано, что список нельзя вызвать.

Не повторяется

Когда что-то происходит is not iterable, проблема, скорее всего, связана с вещью, а не с итерацией. Если вы хотите, чтобы for цикл выполнялся определенное количество раз, вам все равно нужно что-то повторять; a range - обычный выбор. То же самое верно, если вы используете понимание списка и т.д. Для создания нескольких копий значения. Если у вас есть целое число x и вы хотите составить список с одним элементом, который является этим целым числом, который пишется [x], а не list(x).

Это особенно часто встречается'NoneType' object is not iterable. Есть только один 'NoneType' object: специальное значение None - Python запрещает создавать какие-либо другие экземпляры этого класса. Методы Python, которые работают на месте - особенно методы list - обычно возвращают None, а не список, который был изменен. Смотрите также TypeError: объект 'NoneType' не может быть итерирован в Python.

Не вызывается

Если a 'module' object is not callable, это, скорее всего, потому, что вы хотите функцию или класс из модуля, который имеет то же имя, что и модуль, а не сам модуль. Связанный пример предназначен для socket стандартной библиотеки; другие распространенные случаи включают datetime и random.

Также убедитесь, что код не вызывает функцию, и запомните результат, вместо того, чтобы запоминать саму функцию. Это обычная проблема с API, которые ожидают "обратного вызова" функции. (Если вам нужно заранее выбрать аргументы, но фактически не вызывать функцию, см. Как я могу привязать аргументы к функции в Python? .) Иногда люди также пытаются предоставить имя функции в виде строки, вместо того, чтобы предоставлять саму функцию.

Новички иногда ожидают, что смогут выполнить "неявное умножение" в математической формуле так, как это работает в классе математики. В программе на Python (как и в других популярных языках) код типа a(b + c) не умножает целое число a на результат b + c; он пытается вызвать a как если бы это была функция. Смотрите Почему я получаю "TypeError: объект 'int' не вызывается" из кода типа "5 (side_length ** 2)"?.

Не поддается подписке

Иногда люди пытаются получить "цифры" из числа, индексируя его, как если бы это была строка. int и float значения не являются строками; в них нет цифр. Таким образом, это вызовет "не подлежит подписке" TypeError. Числовое значение остается неизменным независимо от того, на какой базе вы их записываете, и есть другие способы записи числа, кроме десятичного основания; поэтому вы несете ответственность за создание соответствующей строки в первую очередь.

Если вы пытаетесь работать с вложенными списками, будьте осторожны при индексации в них. Список типа example = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] должен быть проиндексирован как example[i][j], не например example[i[j]]. Логика здесь должна быть довольно простой: правильный код означает индексировать в example (получение списка целых чисел), а затем индексировать в этот результат. Неправильный код означает использование j в качестве индекса в i first из-за того, как вложены скобки.

Если вы пытаетесь вызвать функцию или использовать класс (например, встроенный range), помните, что при этом используются круглые, а не квадратные скобки:

# WRONG
range[10]
# RIGHT
range(10)
python