【问题标题】:Why does isinstance([1, 2, 3], List[str]) evaluate to true?为什么 isinstance([1, 2, 3], List[str]) 评估为真?
【发布时间】:2015-12-23 17:20:15
【问题描述】:

我在 python3.5 中使用了新的类型提示/键入模块,试图找到一种方法来确认提示的类型是否等于变量的实际类型,并遇到了一些让我感到惊讶的事情。

>>> from typing import List
>>> someList = [1, 2, 3]
>>> isinstance(someList, List[str])
True

继续寻找将变量与其暗示类型进行比较的方法,我也尝试过:

>>> anotherList = ["foo", "bar"]
>>> type(anotherList) is List[str]
False

谁能解释为什么前者的计算结果准确为True

接着往下说,有没有一种可靠的方法来检查变量的类型是否等于来自类型模块的类型?

【问题讨论】:

  • 嗯,一方面,type(x) is aisinstance(x, a) 绝对不是一回事。一个对象可以是多种类型的实例(具有继承层次结构),但type(x) 只为您提供其最具体的单一类型。
  • 是的,我在对其进行了一些测试后才知道这一点。仍然想将它包含在我的问题中,因为在询问有关 Python 中的类型比较的任何内容时,它通常被作为首选。
  • type(['foo', 'bar']) == List[str] 的评估结果是什么?
  • 正如预期的那样,它的计算结果为False,因为type(['foo', 'bar']) 的计算结果为list

标签: python python-3.5


【解决方案1】:

isinstance 不做真正的PEP 484 类型检查。 The documentation 顺便指出:

一般来说,isinstance()issubclass() 不应与类型一起使用。

typing 模块,以及它所基于的collections.abcabc 模块,使用广泛的__instancecheck__ and __subclasscheck__ 魔法使isinstanceissubclass 行为合理。但他们在支持你的案子方面做得还不够。支持它也不是他们的目标。

是否有可靠的方法来检查变量的类型是否等于来自类型模块的类型?

你不是在寻找类型平等。正如您自己注意到的,[1, 2, 3] 的类型是 list,它不等于List[str],也不等于List[int]。您正在寻找类型 checking,这要复杂得多。

考虑一下:

def my_function():
    # ... 1000 lines of very complicated code ...

print(isinstance(my_function, Callable[[], int]))

你希望这个程序打印什么?你不能指望isinstance 在运行时挖掘my_function 并推断它总是返回int。这在 Python 中是不可行的。您要么需要一个“编译”时类型检查器,它可以访问my_function 的结构,要么需要显式类型注释,或者——很可能——两者兼而有之。

【讨论】:

  • 非常感谢您简洁明了的回答。我当然理解为什么你不能指望一个函数来判断另一个函数是否总是返回某种类型的变量,但我想如果一个单一的变量对应于来自类型模块的类型。尽管这可能需要手动检查列表中的每个项目是否属于某种类型,这在处理大型列表或嵌套类型的情况下 (List[Dict[str, List[int]]) 只需要太长时间而不可行。再次感谢您的回答!
  • @McMuffinton 我的意思是my_function 和你的someList 一样是“单一变量”。如果您不希望在运行时推断 my_function 的类型,那么也没有理由期待 someList 的类型。
  • 那么isinstanceissubclass应该做什么?
  • @remus 他们的主要目的是让你反思 Python 的动态类型,它基于一个简单的想法:每个对象都是一个类的实例,它是零个或多个基类的子类。因此,someListlist 的一个实例,它是object 的子类。这些关系决定了方法解析,因此它们很容易被运行时使用。不过,后来,PEP 3119 引入了 ABC 和一种覆盖 isinstance / issubclass 的方法,这让你很困惑。
猜你喜欢
  • 2021-11-01
  • 2023-04-04
  • 2014-05-19
  • 1970-01-01
  • 1970-01-01
  • 2014-02-16
  • 1970-01-01
  • 1970-01-01
  • 2018-07-01
相关资源
最近更新 更多