首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >typing.Any vs object?

typing.Any vs object?
EN

Stack Overflow用户
提问于 2016-10-02 20:38:35
回答 2查看 24.2K关注 0票数 60

在输入时使用typing.Anyobject有什么不同吗?例如:

代码语言:javascript
复制
def get_item(L: list, i: int) -> typing.Any:
    return L[i]

对比:

代码语言:javascript
复制
def get_item(L: list, i: int) -> object:
    return L[i]
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-10-02 20:43:20

是的,这是有区别的。虽然在Python3中,所有对象都是object的实例,包括object本身,但只有Any文档指出类型检查器应该忽略返回值。

Any类型文档字符串声明对象是Any子类,反之亦然:

代码语言:javascript
复制
>>> 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()检查的类型检查器,它检查对象在函数中的实际使用情况)可以很容易地反对始终接受Anyobject

Any type documentation

请注意,将Any类型的值赋给更精确的类型时,不会执行类型检查。

Any的行为与object的行为进行对比。与Any类似,每种类型都是object的子类型。然而,与Any不同的是,事实并非如此: object并不是所有其他类型的子类型。

这意味着当值的类型为object时,类型检查器将拒绝几乎所有对它的操作,并且将其赋给更专用类型的变量(或将其用作返回值)是一个类型错误。

和来自mypy文档部分的。

类型object是另一种类型,它可以将任意类型的实例作为值。与Any不同,object是一个普通的静态类型(类似于Java语言中的Object ),并且只接受对所有类型有效的对象值操作。

object可以被cast到一个更具体的类型,而Any实际上意味着任何事情都会发生,类型检查器会从对象的任何使用中解脱出来(即使您后来将这样的对象分配给一个类型检查的名称)。

通过接受与List[Any]相同的list,您已经将您的函数绘制到了一个无类型的角落。类型检查器在那里被释放,返回值不再重要,但是因为您的函数接受包含Any对象的列表,所以在这里适当的返回值应该是Any

要正确地参与类型检查代码,您需要将输入标记为List[T] (一个通用类型的容器),以便类型检查器能够关心返回值。在您的示例中,它应该是T,因为您要从列表中检索值。从TypeVar创建T

代码语言:javascript
复制
from typing import TypeVar, List

T = TypeVar('T')

def get_item(L: List[T], i: int) -> T:
    return L[i]
票数 70
EN

Stack Overflow用户

发布于 2016-10-03 04:37:10

Anyobject表面上很相似,但实际上在含义上完全相反。

object是Python元类层次结构的根。每个单独的类都继承自object。这意味着在某种意义上,object是您可以赋予值的最具限制性的类型。如果你有一个object类型的值,那么你唯一被允许调用的方法就是那些属于每个单独对象的方法。例如:

代码语言:javascript
复制
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类型的值执行任何可能的方法或操作。例如:

代码语言:javascript
复制
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

  1. 作为混合动态和静态类型代码的一种方式。例如,如果您有许多动态和复杂的函数,并且没有时间完全静态地键入所有这些函数,那么您可以满足于只给它们一个Any的返回类型,以便名义上将它们带入类型检查的工作中。(或者换一种说法,Any是一个有用的工具,用于帮助将未类型检查的代码库分阶段迁移到有类型的代码库)。
  2. 是一种为难以键入的表达式赋予类型的方法。例如,Python的类型注释目前不支持递归类型,这使得像任意JSON字典这样的类型输入变得困难。作为一种临时措施,您可能希望为您的JSON字典提供一种Dict[str, Any]类型,这总比没有好一点。

相反,如果您希望以一种类型安全的方式指示某个值必须与任何可能存在的对象协同工作,请使用object

我的建议是避免使用Any,除非在别无选择的情况下。Any是一种让步--一种允许我们真正生活在类型安全世界中的动态性的机制。

有关详细信息,请参阅:

对于您的特定示例,我将使用TypeVars,而不是object或Any。您想要做的是指示您希望返回列表中包含的任何内容的类型。如果列表将始终包含相同的类型(通常是这种情况),则需要执行以下操作:

代码语言:javascript
复制
from typing import List, TypeVar

T = TypeVar('T')
def get_item(L: List[T], i: int) -> T:
    return L[i]

这样,您的get_item函数将尽可能返回最精确的类型。

票数 19
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39817081

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档