Python objects, types, classes, and instances – a glossary

March 30th, 2012 at 7:35 am

While writing the article on the internals of Python callables, it occurred to me that some things in Python have more than one name. At the same time, some names are sometimes used to refer to more than one entity, and which one is implied has to be understood from context. Therefore, I think it’s a good idea to collect this nomenclature in a single place for the sake of my future writings. This way I’ll just be able to point here every time I discuss these topics, instead of explaining them over and over again.

Specifically, I want to define what I mean by types, objects, classes and instances. Note that this refers to Python 3.x, but is mostly applicable for 2.x as well [1].


It’s easiest to start with objects. The Python data model reference has a pretty good definition:

Objects are Python’s abstraction for data. All data in a Python program is represented by objects or by relations between objects. (In a sense, and in conformance to Von Neumann’s model of a “stored program computer,” code is also represented by objects.)

Every object has an identity, a type and a value.

So, everything in Python is an object. Lists are objects. 42 is an object. Modules are objects. Functions are objects. Python bytecode is also kept in an object. All of these have types and unique IDs:

>>> def foo(): pass
>>> type(foo), id(foo)
(<class 'function'>, 38110760)
>>> type(foo.__code__), id(foo.__code__)
(<class 'code'>, 38111680)

This "everything is an object" model is backed by the CPython implementation. Indeed, if you look into the code of CPython, you’ll notice that every entity mentioned above can be manipulated via a pointer to the PyObject base struct.


The data model reference is useful here too:

[...] An object’s type determines the operations that the object supports (e.g., “does it have a length?”) and also defines the possible values for objects of that type.

So, every object in Python has a type. Its type can be discovered by calling the type builtin function [2]. The type is an object too, so it has a type of its own, which is called type. This last fact may not be very exciting or useful when you’re just writing Python code, but it’s hugely important if you want to understand the internals of CPython:

>>> type(42)
<class 'int'>
>>> type(type(42))
<class 'type'>
>>> type(type(type(42)))
<class 'type'>

Yep, it’s turtles all the way down.


In the olden days, there was a difference between user-defined classes and built in types. But since 2.2, as long as you’re using "new-style" classes (classes that inherit from object in 2.x, and are default in 3.x), there is no real difference. Essentially, a class is a mechanism Python gives us to create new user-defined types from Python code.

>>> class Joe: pass
>>> j = Joe()
>>> type(j)
<class '__main__.Joe'>

Using the class mechanism, we’ve created Joe – a user-defined type. j is an instance of the class Joe. In other words, it’s an object and its type is Joe.

As any other type, Joe is an object itself, and it has a type too. This type is type:

>>> type(type(j))
<class 'type'>

The terms "class" and "type" are an example of two names referring to the same concept. To avoid this confusion, I will always try to say "type" when I mean a type, and "user-defined class" (or "user-defined type") when referring to a new type created using the class construct. Note that when we create new types using the C API of CPython, there’s no "class" mentioned – we create a new "type", not a new "class".


Not unlike the ambiguity between "class" and "type", "instance" is synonymous to "object". Think of it this way: objects are instances of types. So, "42 is an instance of the type int" is equivalent to "42 is an int object". I usually use "instance" and "object" interchangeably. In some cases when I want to specifically refer to objects as artifacts of the CPython implementation, I will try to use "instance" to refer to actual instances of classes. Another place where the term "instance" is explicitly used by Python is in built-ins like isinstance and the special __instancecheck__ attribute.


As we’ve seen, there are two pairs of roughly synonymous terms in Python nomenclature. Types and classes are interchangeable concepts. I prefer to say "type" wherever possible, leaving the term "class" for user-defined types created with the "class" construct. IMHO "type" is a better term, and Python wouldn’t be worse if the "class" concept was wiped out completely.

Similarly, objects and instances are terms that mean the same thing, but perhaps from slightly different angles. Sometimes it’s more convenient to use "instance" (i.e. when specifically talking about specific objects being instances of specific types – as in "j is an instance of Joe"), and sometimes it’s better to use "object" (i.e. when discussing the guts of the CPython implementation).

I sincerely hope this post is more helpful than confusing! For me, it’s an aid that serves as a simple glossary when my usage of these terms in some article may be unclear or ambiguous.

[1] As long as you forget about the existence of classic 2.x classes and take it as a fact that all user-defined classes inherit from object.
[2] An alternative is the __class__ attribute.

Related posts:

  1. The fundamental types of Python – a diagram
  2. Python object creation sequence
  3. 64 bit types on 32 bit machines
  4. Under the hood of Python class definitions
  5. Python internals: how callables work

10 Responses to “Python objects, types, classes, and instances – a glossary”

  1. Nick CoghlanNo Gravatar Says:

    It can also be useful to remember that type(obj) and obj.__class__ aren’t *quite* the same thing. Specifically, they treat proxy objects (including, but not limited to, weakref.proxy) that redirect attribute lookups to another object differently:

    >>> class MyList(list): pass

    >>> x = MyList()
    >>> y = weakref.proxy(x)
    >>> type(y)

    >>> y.__class__

    Since it’s closely related and you’re explaining terminology, you may also want to mention the idea of metaclasses and the fact that the naming chain goes:

    obj – instance object
    type(obj) – class/type object
    type(type(obj)) – metaclass object

  2. elibenNo Gravatar Says:


    Thanks for the clarifications. I didn’t know about the nuance with type and __class__, and actually our official documentation for type says:

    Return the type of an object. The return value is a type object and generally the same object as returned by object.__class__.

    The generally in there must be what you’re referring to.

    As for metaclasses, since I have a separate article about them ( I decided to leave them out for simplicity. I also have a more comprehensive exploration of the type system coming up.

  3. Anthony BarryNo Gravatar Says:

    Thank you. I’ve just started learning python on Coursera which is presented via video lectures and was getting very confused with the way the these terms were being used apparently interchangeably.

  4. ericNo Gravatar Says:

    For the past few days I’ve been trying to hammer home my understanding of object orientation in Python. Python is my first language. It’s difficult to get a grasp of the relationship between many new very abstract terms. Your definitions above are a good help.

    I think the most efficient way forward for me will be to make a venn diagram of these terms and then writing out in english the connections between them, maybe with arrows to code examples. A glossary is necessary but the logical relationship between the terms is difficult to grok when rendered in English.

    A venn diagram of these terms might be very useful for your readers as well.

  5. elibenNo Gravatar Says:


  6. robertNo Gravatar Says:

    I ended up here trying to understand “instances” reported for pywintypes. Regarding the Joe() example and using Python 2.7, when I try the type(j), I get the result below. Is that a difference between Python 2 and 3?

    >>> print sys.version
    2.7.2 (default, Jun 24 2011, 12:21:10) [MSC v.1500 32 bit (Intel)]
    >>> class Joe: pass
    >>> j =Joe()
    >>> type(j)
    <type 'instance'>
  7. elibenNo Gravatar Says:


    Yes, Python 2.x and 3.x are somewhat different in these respects. In Python 2.x classes by default are “old style” classes. To get the new style ones, use class Joe(object). In Python 3.x there are no old style classes.

  8. robertNo Gravatar Says:

    Thanks for the feedback. Seems there are subtleties when I decide to move to Python 3. My current Python use is pedestrian so perhaps these differences do not yet matter as much as available packages.

  9. TomNo Gravatar Says:

    This was really helpful!

  10. wenjianhnNo Gravatar Says:

    Very helpful.

Leave a Reply

To post code with preserved formatting, enclose it in `backticks` (even multiple lines)