Execute Program

Python in Detail: Even Classes Are Objects

Welcome to the Even Classes Are Objects lesson!

This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!

  • In an earlier lesson, we saw that every Python value has attributes. In this lesson, we'll see that every value in Python is an instance of some class.

  • We've already used the type(...) function to get a value's class.

  • >
    type(5).__name__
    Result:
  • When we call type(x), it returns x.__class__. We can also access that attribute directly.

  • >
    (5).__class__.__name__
    Result:
  • >
    ("Amir").__class__.__name__
    Result:
    'str'Pass Icon
  • Our functions are instances of the function class.

  • >
    def double(x):
    return x * 2

    double.__class__.__name__
    Result:
    'function'Pass Icon
  • In Python, classes themselves are also values: we can put them in variables, pass them as functions, etc.

  • >
    class Cat:
    def __init__(self, name):
    self.name = name

    some_class = Cat
    cat = some_class("Keanu")
    cat.name
    Result:
    'Keanu'Pass Icon
  • If classes are values, and all values are instances of a class, then what's the class of a class?

  • >
    class Cat:
    pass

    Cat.__class__.__name__
    Result:
  • This may seem strange, but it's also consistent! In Python, "type" is sometimes used as a synonym for "class". A class like Cat is an instance of type.

  • In that example, we accessed type's .__name__ attribute. type itself is a class, which must be a value, so it must be an object. What's the class of type?

  • >
    type.__class__.__name__
    Result:
  • Classes are instances of the type class. But type itself is also a class, so type is an instance of itself.

  • If type is a class, then we can instantiate it like any other class. Instantiating type is a way to build a new type (a new class). The next example defines a Point class. But instead of using the regular class syntax, we build the class up piece by piece, starting with a call to type(...).

  • >
    # This function will become our Point class's constructor.
    def __init__(self, x, y):
    self.x = x
    self.y = y

    # We build the `Point` class by instantiating the `type` class. It takes a
    # name for the new class, a tuple of base classes, and a dictionary of
    # attributes for the class.
    Point = type(
    "Point",
    (object, ),
    {
    "__init__": __init__,
    }
    )

    # Now we have our `Point` class, which works like any other class!
    p = Point(2, 3)
    (p.x, p.y)
    Result:
    (2, 3)Pass Icon
  • This isn't a good way to define a new class in practice. But it shows us how far Python goes in exposing its internals, and in treating everything as an object. Even the class syntax is just a more convenient way to instantiate the type class.

  • You've reached the end of this course! We thought that this was a good place to end, since it highlights how dynamic Python is. We hope that you enjoyed it!