函数签名中的“类型错误:‘类型’对象不可下标”

yue*_*ter 6 python list typeerror type-hinting python-3.x

为什么我在运行此代码时会收到此错误?

Traceback (most recent call last):                                                                                                                                                  
  File "main.py", line 13, in <module>                                                                                                                                              
    def twoSum(self, nums: list[int], target: int) -> list[int]:                                                                                                                    
TypeError: 'type' object is not subscriptable
Run Code Online (Sandbox Code Playgroud)
nums = [4,5,6,7,8,9]
target = 13

def twoSum(self, nums: list[int], target: int) -> list[int]:
        dictionary = {}
        answer = []
 
        for i in range(len(nums)):
            secondNumber = target-nums[i]
            if(secondNumber in dictionary.keys()):
                secondIndex = nums.index(secondNumber)
                if(i != secondIndex):
                    return sorted([i, secondIndex])
                
            dictionary.update({nums[i]: i})

print(twoSum(nums, target))
Run Code Online (Sandbox Code Playgroud)

dsz*_*dsz 18

将@Nerxis 的评论提升为答案。

对于 Python 3.7 和 3.8,添加:

from __future__ import annotations
Run Code Online (Sandbox Code Playgroud)

作为您第一次导入模块。

List虽然使用代替的接受答案list很好,但当你需要这样做时它不会帮助你pd.Series[np.int64]。使用上面的代替。


Mad*_*ist 8

该表达式list[int]试图为 object 下标list,它是一个类。类对象属于它们的元类的类型,type在这种情况下是。由于type没有定义__getitem__方法,你不能做list[...].

要正确执行此操作,您需要导入typing.List并使用它而不是list类型提示中的内置:

from typing import List

...


def twoSum(self, nums: List[int], target: int) -> List[int]:
Run Code Online (Sandbox Code Playgroud)

如果你想避免额外的导入,你可以简化类型提示以排除泛型:

def twoSum(self, nums: list, target: int) -> list:
Run Code Online (Sandbox Code Playgroud)

或者,您可以完全摆脱类型提示:

def twoSum(self, nums, target):
Run Code Online (Sandbox Code Playgroud)

  • 从 3.7 开始,键入就不再使用元类,因为键入使用不同元类的代码是不可能的。添加了“__class_getitem__”,用于为类型添加下标。另外,你的答案在 Python 3.9+ 中是完全错误的。 (5认同)
  • list[int] 应该与 python 3.9 一起使用。 (4认同)

Kar*_*tel 5

概括

代码中表示函数返回类型的类型注释-> list[int]部分。它是一种特殊的表示法,第三方工具可以使用它对代码进行一些基本的静态类型检查。就 Python 本身而言,它对代码的唯一影响是向函数添加一些元数据:

>>> def example() -> list[int]:
...     pass
... 
>>> 'return' in example.__annotations__
True
Run Code Online (Sandbox Code Playgroud)

Python 本身不会进行任何类型检查:

>>> type(example()) # definitely did not give a list of integers!
<class 'NoneType'>
Run Code Online (Sandbox Code Playgroud)

同样,该部分是参数: list[int]的类型注释。numstwoSum

根据 Python 版本的不同,可能不接受此特定注释。

Python 3.9 及以上版本

该错误是不可重现的。-> list[int]声明该函数旨在返回一个包含所有整数值的列表,并: list[int]声明应传入另一个此类列表 for nums。这些提示允许 MyPy 等第三方工具在代码编译或运行之前查找问题。

Python 3.7 或 3.8

此注释不按原样接受。有两种解决方法:

  1. 使用导入来访问PEP 563__future__中描述的“延迟评估注释”行为:
# At the top of the code, along with the other `import`s
from __future__ import annotations
Run Code Online (Sandbox Code Playgroud)
  1. 使用标准库模块中定义的相应类typing
# At the top of the code
from typing import List

# when annotating the function
def twoSum(self, nums: List[int], target: int) -> List[int]:
Run Code Online (Sandbox Code Playgroud)

注意 中的大写ListL。

Python 3.5 和 3.6

__future__不支持注释。使用typing模块。

Python 3.4 及以下版本

根本不支持类型注释。只需删除它们:

def twoSum(self, nums, target):
Run Code Online (Sandbox Code Playgroud)

再次记住,Python 本身不会对注释做任何有意义的事情。它们不会导致代码引发无效参数的异常、将它们转换为正确的类型或类似的任何内容。它们适用于第三方工具,并且完全可选,除非某些其他第三方工具强制使用它们。