Typing.Any vs object?

Is there a difference between using typing.Any as opposed to object when typing? For example:

 def get_item(L: list, i: int) -> typing.Any: return L[i] 

Compared with:

 def get_item(L: list, i: int) -> object: return L[i] 
+10
python type-hinting
source share
2 answers

Yes, there is a difference. Although in Python 3 all objects are instances of the object , including the object itself, only Any documents whose return values ​​should be ignored by type checking.

A documentation line of type Any states that the object is a subclass of Any and vice versa:

 >>> 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. 

However, a proper type checker (which goes beyond isinstance() and that checks how an object is actually used in a function) can easily object to an object where Any always accepted.

From Any type documentation :

Note that when assigning a value of type Any more accurate type, type checking is not performed.

and

Compare the behavior of Any with the behavior of object . Like Any , each type is a subtype of object . However, unlike Any , the converse is not true: an object is not a subtype of any other type.

This means that when the value type is object , the type checker will reject almost all operations on it, and assigning it to a variable (or using it as a return value) of a more specialized type is a type error.

and from the documentation section of mypy Any against object :

The type object is another type that can have an instance of an arbitrary type as a value. Unlike Any , an object is a regular static type (it is similar to Object in Java), and only values ​​valid for all types are accepted for the values ​​of the object.

object can be cast to a more specific type, while Any really means that something is coming, and the type checker is disconnected from any use of the object (even if you subsequently assign such an object to a name checked by type).

You have already drawn your function in an untyped corner by accepting list , which comes down to the same as List[Any] . Type checking is disabled here, and the return value no longer matters, but since your function accepts a list containing Any objects, the correct return value will be Any here.

To participate in the code being checked correctly, you must mark your input as List[T] (a generic type container) for type checking, so that you can then take care of the return value. Which in your case will be T since you get the value from the list. Create T from TypeVar :

 from typing import TypeVar, List T = TypeVar('T') def get_item(L: List[T], i: int) -> T: return L[i] 
+13
source share

Any and object superficially similar, but actually completely opposite in meaning.

object is the root of the Python metaclass hierarchy. Each class inherits from object . This means that object in a sense is the most restrictive type you can give values. If you have a value of type object , the only methods that you allow to call are those that are part of each individual object. For example:

 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)) 

In contrast, Any is a control hatch that allows you to mix dynamic and statically typed code. Any is the least restrictive type - any possible method or operation is permitted with a value of type Any . For example:

 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)) 

Usually, you should use Any only for cases where ...

  • As a way to combine dynamic and statically typed code. For example, if you have a lot of dynamic and complex functions, and you don’t have time to completely statically enter them all, you can only agree to give them an Any return type in order to nominally bring them to work with type checking. (Or, to put it another way, Any is a useful tool that helps you instantly port untypechecked codebase to a typed codebase).
  • As a way to assign a type to an expression that is hard to type. For example, Python type annotations do not currently support recursive types, which makes typing things like arbitrary JSON dicts difficult. As a temporary measure, you may need to give your JSON dicts the type Dict[str, Any] , which is slightly better than nothing.

In contrast, use object for cases when you want to indicate in the form of a file that the value SHOULD literally work with any possible object.

My recommendation is to avoid using Any , unless there is no alternative. Any is a concession - a mechanism for dynamism, where we really prefer to live in a world of types.

For more information see


In your specific example, I would use TypeVars, not an object or Any. You want to indicate that you want to return the type of what is contained in the list. If the list will always contain the same type (usually it is), you would like:

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

Thus, your get_item function will return the most accurate type as possible.

+6
source share

All Articles