在输入时使用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]
答案 0 :(得分:19)
是的,有区别。虽然在Python 3中,所有对象都是object
的实例,包括object
本身,但只有Any
文件表明返回值应该被类型检查器忽略。
Any
类型docstring声明该对象是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
始终接受Any
。
请注意,在将类型
Any
的值分配给更精确的类型时,不会执行类型检查。
和
将
Any
的行为与object
的行为进行对比。与Any
类似,每种类型都是object
的子类型。但是,与Any
不同,反之则不然:object不是所有其他类型的子类型。这意味着当值的类型为
object
时,类型检查器将拒绝几乎所有操作,并将其分配给更专业类型的变量(或将其用作返回值)类型错误。
并从mypy文档部分Any vs. object:
类型
object
是另一种类型,可以将任意类型的实例作为值。与Any
不同,object
是普通的静态类型(在Java中类似于Object
),并且只接受对所有类型有效的操作。
object
可以cast为更具体的类型,而Any
实际上意味着任何内容,并且类型检查器不会对任何对象的使用脱离(即使您稍后将此类对象分配给 typechecked的名称。)
您已经通过接受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]
答案 1 :(得分:6)
Any
和object
表面上相似,但事实上其意义完全相反。
object
是Python的元类层次结构的 root 。每个类都继承自object
。这意味着object
在某种意义上是您可以赋予值的最严格的类型。如果您具有类型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
是限制性最小的类型 - 类型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 ,而不是对象或Any。你想要做的是表明你想要返回列表中包含的任何类型。如果列表将始终包含相同的类型(通常是这种情况),您可以这样做:
from typing import List, TypeVar
T = TypeVar('T')
def get_item(L: List[T], i: int) -> T:
return L[i]
这样,您的get_item
函数将返回尽可能最精确的类型。