typing.Any
使用和object
打字有什么区别吗?例如:
def get_item(L: list, i: int) -> typing.Any:
return L[i]
相比:
def get_item(L: list, i: int) -> object:
return L[i]
typing.Any
使用和object
打字有什么区别吗?例如:
def get_item(L: list, i: int) -> typing.Any:
return L[i]
相比:
def get_item(L: list, i: int) -> object:
return L[i]
是,有一点不同。尽管在 Python 3 中,所有对象都是 的实例object
,包括object
它自己,但只有Any
返回值应该被类型检查器忽略的文档。
Any
类型 docstring 声明 object 是一个子类,反之亦然Any
:
>>> import typing
>>> print(typing.Any.__doc__)
Special type indicating an unconstrained type.
- Any object is an instance of Any.
- Any class is a subclass of Any.
- As a special case, Any and object are subclasses of each other.
然而,一个适当的类型检查器(一个超越isinstance()
检查,检查对象在函数中的实际使用方式)可以很容易地反对object
whereAny
总是被接受的。
从Any
类型文档:
Any
请注意,将类型的值分配给更精确的类型时,不会执行类型检查。
和
Any
将 的行为与 的行为进行对比object
。与 类似Any
,每种类型都是 的子类型object
。然而,与 不同Any
的是,相反的情况并非如此: object 不是所有其他类型的子类型。这意味着当值的类型为 时
object
,类型检查器将拒绝对其进行的几乎所有操作,并将其分配给更专业类型的变量(或将其用作返回值)是类型错误。
并来自 mypy 文档部分Any vs. object:
该类型
object
是另一种可以将任意类型的实例作为值的类型。不同于Any
,object
是一个普通的静态类型(类似于Object
Java 中的),对象值只接受对所有类型都有效的操作。
object
可以转换为更具体的类型,而Any
实际上意味着任何事情都会发生,并且类型检查器会脱离对对象的任何使用(即使您稍后将此类对象分配给经过类型检查的名称)。
您已经通过接受将您的函数绘制成一个未键入的角落list
,这归结为与List[Any]
. 类型检查器在那里脱离并且返回值不再重要,但是由于您的函数接受包含Any
对象的列表,因此正确的返回值将在Any
这里。
要正确参与类型检查代码,您需要将输入标记为List[T]
(一般类型的容器),以便类型检查器能够关心返回值。在您的情况下,这是T
因为您正在从列表中检索一个值。T
从创建TypeVar
:
from typing import TypeVar, List
T = TypeVar('T')
def get_item(L: List[T], i: int) -> T:
return L[i]
Any
和object
表面上相似,但实际上意义完全相反。
object
是 Python 元类层次结构的根。每个类都继承自object
. 这意味着从object
某种意义上说,这是您可以赋予值的最严格的类型。如果你有一个 type 的值,那么你object
唯一被允许调用的方法是每个对象的一部分。例如:
foo = 3 # type: object
# Error, not all objects have a method 'hello'
bar = foo.hello()
# OK, all objects have a __str__ method
print(str(foo))
相反,Any
它是一个逃生舱口,旨在让您将动态和静态类型的代码混合在一起。Any
是限制最少的类型 - 任何可能的方法或操作都允许对 type 的值Any
。例如:
from typing import Any
foo = 3 # type: Any
# OK, foo could be any type, and that type might have a 'hello' method
# Since we have no idea what hello() is, `bar` will also have a type of Any
bar = foo.hello()
# Ok, for similar reasons
print(str(foo))
您通常应该尝试Any
仅在以下情况下使用...
Dict[str, Any]
,这比没有好一点。相反,object
用于您希望以类型安全的方式指示值必须从字面上与存在的任何可能对象一起使用的情况。
我的建议是避免使用,Any
除非在别无选择的情况下。Any
是一种让步——一种允许我们真正宁愿生活在类型安全世界中的活力的机制。
有关更多信息,请参阅:
对于您的特定示例,我将使用TypeVars,而不是 object 或 Any。您要做的是表明您要返回列表中包含的任何内容的类型。如果列表将始终包含相同的类型(通常是这种情况),您会想要这样做:
from typing import List, TypeVar
T = TypeVar('T')
def get_item(L: List[T], i: int) -> T:
return L[i]
这样,您的get_item
函数将尽可能返回最精确的类型。