Kar*_*tel 11 python debugging typeerror
我经常从我的 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
Run Code Online (Sandbox Code Playgroud)
当尝试使用库中的函数、方法或类时,我还看到了自定义消息。
什么是TypeError? 这样的消息是什么意思?我该如何理解并解决问题?
如果您的问题作为此问题的重复项而被关闭,请仔细阅读并遵循此处的建议,并在再次询问之前尝试调试代码并研究任何剩余问题。Stack Overflow 不是调试服务。
关于 a 的有效的、非重复的问题TypeError将询问为什么一个特定的、最小的、可重现的示例会导致 a TypeError,并解释您期望发生的情况以及原因。
Kar*_*tel 12
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'>
Run Code Online (Sandbox Code Playgroud)
值得注意的是, 的类型type 是type它本身。
您可能会注意到,Python (3.x) 使用单词 来显示这些类型对象class。这是一个有用的提醒:当您创建 时class,您正在定义一种新的数据类型。这就是课程的目的。
我们可以将示例分为几类:
>>> 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'>
Run Code Online (Sandbox Code Playgroud)
()这些异常告诉您用于调用func(或创建 的实例)的参数(您在 之间放置的内容MyClass)是错误的。要么太多,要么不够,要么没有正确标记。
诚然,这有点令人困惑。我们试图调用一个函数,而我们调用的是一个函数——所以类型实际上是匹配的。已确定的问题在于参数的数量。然而,Python 将其报告为 aTypeError而不是ValueError. 这可能是为了让来自其他语言(例如 C++)的程序员看起来更熟悉,其中“类型”在编译时进行检查,并且可能非常复杂 - 例如接受不同类型或数量的参数的函数本身被认为具有不同种类。
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
Run Code Online (Sandbox Code Playgroud)
这些异常告诉您运算符的左侧和右侧(如+or>或 之类的符号^,用于计算结果)没有意义。例如,尝试对字符串进行除法或减法,或者将字符串重复非整数次,或者(在 3.x 中)将字符串与数字进行比较。作为一种特殊情况,您可以+在两个字符串(或列表或元组)之间使用,但它不会在数学意义上“添加”它们。如果尝试+在整数和字符串之间使用,错误消息将根据顺序而有所不同。
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
Run Code Online (Sandbox Code Playgroud)
这些有点棘手。该%运算符用于获取模数(数字相除时的余数),但也可以通过替换一些占位符来用于格式化字符串。(这是一个过时的系统,很难正确使用,并且有奇怪的特殊情况;在新代码中,请使用 f 字符串或.format方法。)
出现错误是因为左侧字符串中的占位符与右侧的占位符不匹配。在第二种情况下,您可能实际上想要计算模数,因此左侧应该是一个数字(很可能是一个整数)。这些是否应该改为 s 是有争议的,因为字符串的内容ValueError可能是错误的。然而,Python 无法读懂你的想法。
TypeError: %d format: a number is required, not str
TypeError: not all arguments converted during string formatting
Run Code Online (Sandbox Code Playgroud)
这也是一个运算符的问题,这次是[]运算符(用于对列表进行索引、对列表进行切片或在字典中查找键)。[]如果我们在以字符串为键的字典中查找键,那么字符串在 中是有意义的;但我们不能用它来索引列表。
TypeError: list indices must be integers or slices, not str
Run Code Online (Sandbox Code Playgroud)
这意味着错误的内容被传递给内置函数(或另一个可调用函数,例如类型)。从库中获取的函数可能会TypeError通过自定义消息引发自己的 s。该消息应该非常简单。
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'
Run Code Online (Sandbox Code Playgroud)
这是非常不寻常的,大多数问这个问题的人永远不会遇到它(除了datetime标准库模块之外)。发生这种情况是因为尝试像使用函数一样使用方法,但给它提供了错误的类型self:例如,int.to_bytes('1')。该代码是错误的,因为'1'是一个字符串,而字符串不支持.to_bytes. Python 不会将字符串转换为整数;它不能给出 anAttributeError相反,因为是在类中to_bytes查找的,而不是在字符串上查找的。
TypeError: descriptor 'to_bytes' for 'int' objects doesn't apply to a 'str' object
Run Code Online (Sandbox Code Playgroud)
这些含义正是它们听起来的样子。“iterable”的意思是“能够被迭代”;即,反复检查以获得单独的值。这种情况发生在for循环、推导式以及尝试转换为列表时等。消息的“解包”变体是由于尝试在不可迭代上使用解包语法而产生的。
“callable”的意思是“能够被调用”;“调用”某个东西就是()在它后面写(可能在 之间有参数())。类似的代码1('test')没有意义,因为1它不是函数(或类型)。
“可订阅”是指“能够被订阅”;这里,“下标”意味着使用切片语法(x[1:2:3]),或者索引或查找键(x['test'])。我们只能使用序列(如lists 或strings)和映射(如dicts)来做到这一点。
首先,查看回溯以查看代码中发生错误的位置。如果它在库中,请向后工作到代码使用该库的位置。然后仔细阅读错误消息,并将其与代码进行比较,找出导致投诉的原因。最后仔细思考一下:是操作错误,还是价值观错误?
(去做)
您是否可能重新分配内置可调用对象的名称,例如stror inputor list?您是否尝试为两个不同的事物重用一个名称(例如,一个函数及其使用的一些全局数据)?
Python 中的名称一次只能指代一件事。如果您使用,例如,list作为变量名称,那么它不再是“列表的抽象概念”的名称,因此您不能使用它来创建更多列表(包括将其他内容转换为列表) )。如果您使用months字符串列表创建一个全局变量,然后编写一个函数months,该函数会替换该列表,并且该函数的代码无法查找该列表。使用from some_module import *语法时很容易意外发生这种情况。
同样,如果您尝试创建一个方法使用与实例的数据属性相同的名称的类,也会导致同样的问题。(还有一个棘手的特殊情况@staticmethod)。
有时,人们期望能够像 Numpy 数组一样使用列表,并将操作或函数调用“广播”到列表的每个元素。那是行不通的。请改用列表理解。
None考虑一下是否需要作为特殊情况来处理None。但首先要尽量避免陷入这种情况;正如他们所说,“特殊情况还不足以违反规则”。
如果某些事情没有像您期望的那样工作(例如,尝试减去datetime.times或将用户定义类的实例序列化为 JSON) - 不要尝试将问题视为调试问题,而是搜索解决方案你想要那部分代码做的事。
你是从input函数中得到的吗?这会给你一个str,即使它看起来像一个数字。请参阅如何将输入读取为数字?。
您是否忘记调用函数或创建类的实例?
错误消息会告诉你函数的名称;因此,请查看调用该函数的行的部分,并检查参数。位置参数的数量是否正确?是否存在必须提供但缺失的关键字参数?是否存在不应提供的关键字参数?是否有一个位置参数也由关键字提供?
如果您正在为类编写方法,请记住考虑到self. 对于实例方法来说这是必要的。如果您正在调用一个方法,请记住它将self被计为一个参数(“所需”数量和“给定”数量)。
classmethod初学者常见的一个错误是尝试使用类中的方法(不是)而不实例化它。你会做类似的事情
value = MyClass.method(things)
Run Code Online (Sandbox Code Playgroud)
你应该在哪里做类似的事情
instance = MyCLass()
value = instance.method(things)
Run Code Online (Sandbox Code Playgroud)
它(模糊地)instance作为第一个 ( self) 参数传递给method, 并things作为第二个参数。
如果您使用的回调从间接源获取参数,请检查源。
如果您尝试创建自己的类的实例并获取 from TypeError,__init__请确保您确实编写了一个__init__.
如果您不知道参数应该是什么,请查看文档。如果参数有意义,则该函数可能是错误的 - 确保您没有将其与同一库中的另一个函数混淆。
确保运算符对于您希望代码执行的操作正确无误(例如:^ 不是求幂;您想要**),然后检查操作数类型。
在大多数情况下,转换类型是合适的 - 但请仔细考虑。确保该操作对于新类型有意义。例如,如果代码是l + 'second',并且是当前包含 的la ,那么我们很可能不想连接字符串,而是创建一个也有作为元素的修改列表。所以实际上我们想“添加”另一个列表:。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 字符串或.format方法- 这些更容易调试,并且特殊情况较少。但更有可能的是,左侧是一些类似的字符串'1',应该首先转换为int(或者可能 float)。
Python 的错误消息相当晦涩难懂——它使用的术语是大多数程序员很少担心的。但一旦识别出来,错误就很容易进行模式匹配。如果可以在没有参数的情况下实例化该类,请特别注意 - 实例化该类仍然需要一对()空括号;否则,代码引用类本身。需要一个实例才能使用方法。
“一元”运算符(例如bad operand type for unary +: 'str')的“错误操作数”可能是由杂散逗号引起的。'a', + 'b'不等于'a' + 'b'; 它试图用作字符串+上的一元运算符'b',然后创建一个元组。(你知道如何写eg-1来得到负数吗?-有一个一元运算符。事实证明你也可以类似地写;当然,+1它的意思与 相同。)1
特别是如果您必须将代码从 2.x 迁移到 3.x,请非常小心3.x 中的bytes和str类型之间的区别。bytes代表原始数据;str代表文本。这些是根本不同且不相关的事物,只能通过使用编码从一种转换为另一种。在 Python 3.x 中,以二进制模式打开的文件('b'在模式字符串中使用)会bytes在读取时生成,并且必须在写入时提供与bytes写入时兼容的内容。str不符合资格;您必须显式指定编码。这个问题的典型是“TypeError: a bytes-like object is required, not 'str'” 在 Python 3 中处理文件内容时。
Python 无法读取你的意图。例如,访问列表的元素是使用[],而不是()。如果代码()相反,这将被解释为尝试调用列表,因此错误消息将抱怨该列表不可调用。
当某事发生时is not iterable,问题很可能出在该事物上,而不是迭代上。如果你想让一个for循环运行特定的次数,你仍然需要一些东西来迭代;arange是通常的选择。如果您使用列表理解等来制作值的多个副本,情况也是如此。如果你有一个整数x,并且想要创建一个包含一项的列表,即该整数,拼写为[x],而不是list(x)。
尤其常见'NoneType' object is not iterable。只有一个'NoneType' object:特殊值None- Python 禁止创建该类的更多实例。就地工作的 Python 方法(尤其是列表方法)通常返回None而不是被修改的列表。另请参见TypeError: 'NoneType' object is not iterable in Python。
如果是 a 'module' object is not callable,很可能是因为您想要模块中的函数或类,该函数或类与模块同名,而不是模块本身。链接的示例适用于socket标准库;其他常见情况包括datetime和random。
还要确保代码不会调用函数并记住结果,而不是记住函数本身。这是需要“回调”函数的 API 的常见问题。(如果您需要提前选择参数,但实际上并不调用函数,请参阅如何将参数绑定到 Python 中的函数?。)有时人们也会尝试以字符串形式提供函数名称,而不是提供函数本身。
初学者有时希望能够在数学公式中进行“隐式乘法”,就像数学课上的那样。在 Python 程序中(与其他流行语言一样),类似的代码a(b + c) 不会将整数乘以;a的结果。b + c它尝试a像函数一样进行调用。请参阅为什么我会从“5(side_length**2)”这样的代码中收到“TypeError: 'int' object is not callable”?。
有时,人们尝试通过对数字进行索引来从数字中获取“数字”,就好像它是一个字符串一样。int并且float值不是字符串;他们里面没有数字。所以这会导致“不可下标” TypeError。无论以什么基数书写,数值都是相同的,并且除了以十为基数之外,还有其他书写方式;因此,您有责任首先创建适当的字符串。
如果您尝试使用嵌套列表,请小心对它们进行索引。像这样的列表example = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]应该像这样索引example[i][j],而不是例如example[i[j]]。这里的逻辑应该非常简单:正确的代码意味着索引example(获取整数列表),然后索引到该结果。由于括号的j嵌套方式,错误的代码意味着用作第一个索引。i
如果您尝试调用函数或使用类(例如内置range),请记住这使用括号,而不是方括号:
# WRONG
range[10]
# RIGHT
range(10)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8049 次 |
| 最近记录: |