Yes, there is a difference. Although in Python 3, all objects are instances of object, including object itself, only Any documents that the return value should be disregarded by the typechecker.

The Any type docstring states that 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 typechecker (one that goes beyond isinstance() checks, and which inspects how the object is actually used in the function) can readily object to object where Any is always accepted.

From the Any type documentation:

Notice that no typechecking is performed when assigning a value of type Any to a more precise type.

and

Contrast the behavior of Any with the behavior of object. Similar to Any, every type is a subtype of object. However, unlike Any, the reverse is not true: object is not a subtype of every other type.

That means when the type of a value is object, a 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 mypy documentation section Any vs. object:

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

object can be cast to a more specific type, while Any really means anything goes and a type checker disengages from any use of the object (even if you later assign such an object to a name that is typechecked).

You already painted your function into a an un-typed corner by accepting list, which comes down to being the same thing as List[Any]. The typechecker disengaged there and the return value no longer matters, but since your function accepts a list containing Any objects, the proper return value would be Any here.

To properly participate in type-checked code, you need to mark your input as List[T] (a genericly typed container) for a typechecker to then be able to care about the return value. Which in your case would be T since you are retrieving a value from the list. Create T from a TypeVar:

from typing import TypeVar, List

T = TypeVar('T')

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

or, using Python 3.12 or newer:

def get_itemT -> T:
    return L[i]
Answer from Martijn Pieters on Stack Overflow
Top answer
1 of 2
151

Yes, there is a difference. Although in Python 3, all objects are instances of object, including object itself, only Any documents that the return value should be disregarded by the typechecker.

The Any type docstring states that 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 typechecker (one that goes beyond isinstance() checks, and which inspects how the object is actually used in the function) can readily object to object where Any is always accepted.

From the Any type documentation:

Notice that no typechecking is performed when assigning a value of type Any to a more precise type.

and

Contrast the behavior of Any with the behavior of object. Similar to Any, every type is a subtype of object. However, unlike Any, the reverse is not true: object is not a subtype of every other type.

That means when the type of a value is object, a 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 mypy documentation section Any vs. object:

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

object can be cast to a more specific type, while Any really means anything goes and a type checker disengages from any use of the object (even if you later assign such an object to a name that is typechecked).

You already painted your function into a an un-typed corner by accepting list, which comes down to being the same thing as List[Any]. The typechecker disengaged there and the return value no longer matters, but since your function accepts a list containing Any objects, the proper return value would be Any here.

To properly participate in type-checked code, you need to mark your input as List[T] (a genericly typed container) for a typechecker to then be able to care about the return value. Which in your case would be T since you are retrieving a value from the list. Create T from a TypeVar:

from typing import TypeVar, List

T = TypeVar('T')

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

or, using Python 3.12 or newer:

def get_itemT -> T:
    return L[i]
2 of 2
45

Any and object are superficially similar, but in fact are entirely opposite in meaning.

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

foo: object = 3

# 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 an escape hatch meant to allow you to mix together dynamic and statically typed code. Any is the least restrictive type -- any possible method or operation is permitted on a value of type Any. For example:

from typing import Any
foo: Any = 3

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

You should generally try and use Any only for cases where...

  1. 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).
  2. 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 Dict[str, Any], which is a bit better then nothing.

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

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

For more information, see:

  • https://docs.python.org/3/library/typing.html#the-any-type
  • http://mypy.readthedocs.io/en/latest/kinds_of_types.html#the-any-type

For your particular example, I would use TypeVars, 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:

from typing import List, TypeVar

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

This way, your get_item function will return the most precise type as possible.

🌐
Python documentation
docs.python.org › 3 › library › typing.html
typing — Support for type hints
Similarly, Mapping only accepts two type arguments: the first indicates the type of the keys, and the second indicates the type of the values. Unlike most other Python containers, however, it is common in idiomatic Python code for tuples to have elements which are not all of the same type.
🌐
FastAPI
fastapi.tiangolo.com › python-types
Python Types Intro - FastAPI
This is also the main place you would use them with FastAPI. You can declare all the standard Python types, not only str. ... def get_items(item_a: str, item_b: int, item_c: float, item_d: bool, item_e: bytes): return item_a, item_b, item_c, item_d, item_e · For some additional use cases, you might need to import some things from the standard library typing module, for example when you want to declare that something has "any type", you can use Any from typing:
🌐
W3Schools
w3schools.com › python › python_datatypes.asp
Python Data Types
Variables can store data of different types, and different types can do different things. Python has the following data types built-in by default, in these categories:
🌐
Python
typing.python.org › en › latest › spec › concepts.html
Type system concepts — typing documentation
For example, a dictionary can be ... runtime checking of the value type. A gradual type system is one in which a special “unknown” or “dynamic” type is used to describe names or expressions whose types are not known statically. In Python, this type is spelled ...
🌐
Python
typing.python.org › en › latest › spec › special-types.html
Special types in annotations — typing documentation
A type checker ought to flag violations of such assumptions, but by default constructor calls that match the constructor signature in the indicated base class (User in the example above) should be allowed. A program containing a complex or extensible class hierarchy might also handle this by using a factory class method. When type is parameterized it requires exactly one parameter. Plain type without brackets, the root of Python’s metaclass hierarchy, is equivalent to type[Any].
🌐
DigitalOcean
digitalocean.com › community › tutorials › python-type
Python type() Function Explained | DigitalOcean
June 6, 2025 - Python’s type() function is a built-in that serves a dual purpose: determining an object’s exact class and dynamically creating new classes at runtime.
🌐
Adam Johnson
adamj.eu › tech › 2021 › 05 › 07 › python-type-hints-use-object-instead-of-any
Python type hints: Use object instead of Any - Adam Johnson
When starting out with Python type hints, it’s common to overuse typing.Any. This is dangerous, since Any entirely disables type checking for a variable, allowing any operation. If you’re using Any to mean “this object could be any type, and I don’t care what”, you probably want to use object instead...
Find elsewhere
🌐
Python.org
discuss.python.org › ideas
Making Any a builtin object, referring to typing.Any - Ideas - Discussions on Python.org
March 29, 2022 - Has there been active discussion of making Any a keyword in the language? Now that 3.6 is EOL, I’m finding a lot of my projects are making changes like so: +from __future__ import annotations + -from typing import Optional, Any, Dict +from typing import Any class Foo: - bar: Optional[Dict[str, Any]] + bar: dict[str, Any] | None This is happening in many modules across several different kinds of projects – libraries and applications.
🌐
Programiz
programiz.com › python-programming › methods › built-in › type
Python type()
Created with over a decade of experience and thousands of feedback. ... Try Programiz PRO! ... Become a certified Python programmer. Try Programiz PRO! ... The type() function either returns the type of the object or returns a new type object based on the arguments passed. ... The type() function either takes a single object parameter. ... dict - a dictionary which is the namespace containing definitions for the class body; becomes the __dict__ attribute
🌐
Python
docs.python.org › 3 › library › types.html
types — Dynamic type creation and names for built-in types
This module provides names for many of the types that are required to implement a Python interpreter. It deliberately avoids including some of the types that arise only incidentally during processing such as the listiterator type. Typical use of these names is for isinstance() or issubclass() checks. If you instantiate any of these types, note that signatures may vary between Python versions.
Top answer
1 of 3
19

I'll answer the 1,2 question first, then 4th then 3rd:

  • "Whats the relationship between a type type "objects" and "class instances" type objects?"
  • "Can I assume the ~meta API to in-built type objects is the same as that of "class instance" type objects?"

They are the same, and yes they share a common API. When the documentation describes built in types as "objects", or class instances as "objects", or a class or whatever as an "object" ... they are talking about exactly the same language construct.

  • "In general, what are "objects" ..."

The object is a foundational language feature in Python that supports attributes and behaviors much like other OOPLs. All Python objects also have a class much like other classed based OOPLs. The object class is the base of the class hierarchy in Python. Thus all classes are subclasses of the object class, and all the aforementioned "objects" and instances of object - by way of inheritance.

It's worth first pointing out explicitly that in Python (2.2 and above) "type" and "class" mean the same thing (for all intents and purposes). So "int", and the rest of the so called builtin types are classes (which are represented as objects of course). For example this x = int(1) calls the int class (object) to construct an int instance object, x.

It's true to say there are two types of object in Python; "type" objects, or those that represent types, and "non-type" objects - those that don't. But it's equally true to say there are two type of integers; zero, and not zero. It doesn't mean much: Everything in Python is an object including classes. Since classes form a kind object, they are all instances of a class called "type". The type object is also an instance of type. Note you can inspect the inheritance hierarchy of class by examining the _bases_ attribute of a class object. In all cases it leads back to the object class - of course. See https://www.eecg.utoronto.ca/~jzhu/csc326/readings/metaclass-class-instance.pdf for further details on this.

  • "...where is it all documented?"

Well, that's actually a good question. It should be covered in the Data Model section of the language reference, but it is sort of skimmed over. The constructor for object objects, object (that made sense) is a built in and documented with the rest of the builtins here. Also the Classes chapter of The Python Tutorial also covers this area a bit.

2 of 3
2

It's a bit hard to understand what you are asking.

A type is the class of a class. Like everything else in Python, classes themselves are objects, and you can pass them around, assign them to variables, etc. If you ask a class what its class is, you will get the answer type. If you ask a class instance what its class is, you will of course get the class.

>>> type(int)
<type 'type'>
>>> type(1)
<type 'int'>

>>> class Foo(object):
...   pass
>>> type(Foo)
<type 'type'>
>>> obj = Foo()
>>> type(obj)
<class '__main__.Foo'>

(here the function type(x) is another way of doing x.__class__.)

🌐
Real Python
realpython.com › python-data-types
Basic Data Types in Python: A Quick Exploration – Real Python
December 21, 2024 - Integer numbers are whole numbers with no decimal places. They can be positive or negative numbers. For example, 0, 1, 2, 3, -1, -2, and -3 are all integers. Usually, you’ll use positive integer numbers to count things. In Python, the integer data type is represented by the int class:
🌐
Python documentation
docs.python.org › 3 › library › functions.html
Built-in Functions — Python 3.14.3 documentation
The Python interpreter has a number of functions and types built into it that are always available. They are listed here in alphabetical order. ... Return the absolute value of a number. The argument may be an integer, a floating-point number, or an object implementing __abs__(). If the argument is a complex number, its magnitude is returned.
🌐
Python documentation
docs.python.org › 3 › library › stdtypes.html
Built-in Types — Python 3.14.3 documentation
Some operations are supported by several object types; in particular, practically all objects can be compared for equality, tested for truth value, and converted to a string (with the repr() function or the slightly different str() function). The latter function is implicitly used when an object ...
🌐
Pluralsight
pluralsight.com › tech insights & how-to guides › software development
Data Types in Python Explained | Pluralsight
Python's simple types, like integers and floats, behave similarly to primitives in other languages for efficiency. The distinction between primitive and reference object is mostly academic but important when considering performance and behavior, such as immutability and how data is passed in functions (by object reference).
🌐
W3Schools
w3schools.com › python › ref_func_type.asp
Python type() Function
Sign In ★ +1 Get Certified Upgrade Teachers Spaces Bootcamps Get Certified Upgrade Teachers Spaces Bootcamps ... HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP HOW TO W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS DSA TYPESCRIPT ANGULAR ANGULARJS GIT POSTGRESQL ...
🌐
Real Python
realpython.com › python-type-checking
Python Type Checking (Guide) – Real Python
July 15, 2024 - All programming languages include some kind of type system that formalizes which categories of objects it can work with and how those categories are treated. For instance, a type system can define a numerical type, with 42 as one example of an object of numerical type. ... Python is a dynamically typed language.
Top answer
1 of 1
2

Depending on what exactly you want to use, there are two different options:

  1. If you want to basically opt-out of type-checking any_value completely and indicate it could be literally any type with zero restrictions, use typing.Any. Example:

    from typing import Any
    
    class MyThing:
        def update(self, col_name: str, new_value: Any) -> None:
            # Note: this typechecks; new_value can be anything, and 
            # that object might have a foo method
            new_value.foo()  
            # ...snip...
    
  2. If you want to indicate that new_value can be of any type, but also want to ensure that the update method only ever uses new_value in a fully typesafe way, I would use object, which is the base type of every type in Python:

    class MyThing:
        def update(self, col_name: str, new_value: object) -> None:
            # Note: this does not typecheck since new_value is of
            # type 'object', and 'object' is not guaranteed to have
            # a method named 'foo'
            new_value.foo()  
            # ...snip...
    

I personally bias towards using object -- Any is designed specifically as a "bridge" that lets you mix the typed and untyped worlds within your program. I personally think it's easier to reason about code if you keep those two worlds fairly distinct (e.g. by having a fully typed "core" possibly with a bunch of untyped code wrapping it) instead of a method that's both statically and dynamically typed.

Of course, it's not always possible to do this...

(We would like the type hint for documentation purposes, to make the code easier to read)

As an aside/as a suggestion, if you're going to use type hints, I would also strongly recommend going all the way and actually type-check your code using tools like mypy as a part of your development process.

Using type hints for documentation is great, but it can be very confusing if your code doesn't conform to the documentation. Since we have tools to automatically typecheck our code using those type hints, we might as well (and gain that extra guarantee).

(Pragmatically, trying to typecheck your entire codebase all at once can lead to a lot of noise -- what you can try and do instead is progressively typecheck your codebase. For example, you can configure mypy to typecheck only a set list of files (that you maybe grow over time?), make certain checks stricter or looser (perhaps on a per-file basis), and so forth. This works well with the "typed core, untyped wrapper" strategy mentioned above.)