typing.Any vs object?
<p>Is there any difference between using <code>typing.Any</code> as opposed to <code>object</code> in typing? For example:</p>

<pre><code>def get_item(L: list, i: int) -&gt; typing.Any:
    return L[i]
</code></pre>

<p>Compared to:</p>

<pre><code>def get_item(L: list, i: int) -&gt; object:
    return L[i]
</code></pre>

<p><code>Any</code> and <code>object</code> are superficially similar, but in fact are entirely <em>opposite</em> in meaning.</p>

<p><code>object</code> is the <em>root</em> of Python's metaclass hierarchy. Every single class inherits from <code>object</code>. That means that <code>object</code> is in a certain sense the most restrictive type you can give values. If you have a value of type <code>object</code>, the only methods you are permitted to call are ones that are a part of every single object. For example:</p>

<pre><code>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))   
</code></pre>

<p>In contrast, <code>Any</code> is an <em>escape hatch</em> meant to allow you to mix together dynamic and statically typed code. <code>Any</code> is the least restrictive type -- any possible method or operation is permitted on a value of type <code>Any</code>. For example:</p>

<pre><code>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))
</code></pre>

<p>You should generally try and use <code>Any</code> only for cases where...</p>

<ol>
<li>As a way of mixing together dynamic and statically typed code. For example, if you have many dynamic and complex functions, and don't have time to fully statically type all of them, you could settle for just giving them a return type of Any to nominally bring them into the typechecked work. (Or to put it another way, Any is a useful tool for helping migrate an untypechecked codebase to a typed codebase in stages).</li>
<li>As a way of giving a type to an expression that is difficult to type. For example, Python's type annotations currently do not support recursive types, which makes typing things like arbitrary JSON dicts difficult. As a temporary measure, you might want to give your JSON dicts a type of <code>Dict[str, Any]</code>, which is a bit better then nothing.</li>
</ol>

<p>In contrast, use <code>object</code> for cases where you want to indicate in a typesafe way that a value MUST literally work with any possible object in existence.</p>

<p>My recommendation is to avoid using <code>Any</code> except in cases where there is no alternative. <code>Any</code> is a concession -- a mechanism for allowing dynamism where we'd really rather live in a typesafe world.</p>

<p>For more information, see:</p>

<ul>
<li><a href="https://docs.python.org/3/library/typing.html#the-any-type" rel="nofollow">https://docs.python.org/3/library/typing.html#the-any-type</a></li>
<li><a href="http://mypy.readthedocs.io/en/latest/kinds_of_types.html#the-any-type" rel="nofollow">http://mypy.readthedocs.io/en/latest/kinds_of_types.html#the-any-type</a></li>
</ul>

<hr>

<p>For your particular example, I would use <em>TypeVars</em>, rather then either object or Any. What you want to do is to indicate that you want to return the type of whatever is contained within the list. If the list will always contain the same type (which is typically the case), you would want to do:</p>

<pre><code>from typing import List, TypeVar

T = TypeVar('T')
def get_item(L: List[T], i: int) -&gt; T:
    return L[i]
</code></pre>

<p>This way, your <code>get_item</code> function will return the most precise type as possible.</p>

python python-3.5 type-hinting