The Python type() function is a basic Python function for working with types. As part of the Python im­ple­men­ta­tion, it belongs to the core of the language.

What is the type() function in Python for?

The Python type() function is used in two different scenarios:

  1. To get the type of a Python object
  2. To dy­nam­i­cal­ly create a new type

Let’s consider the first case which is much more useful in day-to-day use.

Get the type of an object with type()

Python is a dynamic language. This means that types are only de­ter­mined at runtime and are bound to values instead of variables. From this cir­cum­stance arises the necessity to determine the type of an object at runtime.

Let’s call Python’s type() function and pass an object as the only parameter. In return we get the type of the object, e.g. int or str:

# Type of `42` is `int`
assert type(42) == int
# Type of `str(42)` is `str`
assert type(str(42)) == str
Python

If we call the type() function in the Python REPL, the textual rep­re­sen­ta­tion of the returned object will mention “class” instead of “type”:

# Returns "<class 'int'>" inside REPL
type(42)
Python

What seems confusing at first makes perfect sense, because in Python, “every­thing is an object”. In Python, the object type cor­re­sponds to its class. Thus, calling the type() function is generally equiv­a­lent to reading the __class__ attribute:

# Should hold in most cases
assert type(obj) is obj.__class__
Python

Create a new type with type()

Now, let’s explore the second possible use of the type() function. When called with three arguments, the function enables us to dy­nam­i­cal­ly create a new type:

type(name, bases, dict, **kwds)
Python

In this form, the Python type() function behaves similarly to the class keyword. The code type = type("Type", bases, dict) can be thought of as an equiv­a­lent class de­f­i­n­i­tion:

class <Type>(<bases>):
    <dict>
Python

Below is an example of using Python type() to create new types. Here’s an overview of the arguments:

name bases dict **kwds
Name of the new type as string Tuple with base classes Dict with at­trib­ut­es of the new class Ad­di­tion­al arguments for metaclass in­stan­ti­a­tion
Tip

With Deploy Now from IONOS you can deploy websites and apps easily using GitHub.

How does Python type() work?

When using the type() function to determine the type of an object, the return value isn’t a string, but an in­de­pen­dent object:

# Value returned by `type(42)` is not a string
assert type(42) != 'int'
# We get back an object named `int`
assert type(42) == int
Python

Let’s look at a few examples of return values of the type() function for objects of different types:

# Python objects of different types
different_objs = None, True, 42, 'John', ('Walter', 'White'), ...
# Print out the type of each object
for obj in different_objs:
    print(f"{obj}: {type(obj)}")
Python
type() call Textual rep­re­sen­ta­tion
type(None) <class 'NoneType'>
type(True) <class 'bool'>
type(42) <class 'int'>
type('John') <class 'str'>
type(('Walter', 'White')) <class 'tuple'>
type(...) <class 'ellipsis'>

The question arises: what’s the type of the object returned by type()? Let’s try it out. We call the Python type() function and pass the return value of another type() call:

# Returns: "<class 'type'>"
type(type(42))
Python

It shows that in addition to Python’s built-in type() function, there’s the type type of the same name. This type rep­re­sents all other Python types, as il­lus­trat­ed through an example:

# DifferentPython objects
different_objs = None, True, 42, 'John', ('Walter', 'White'), ...
# Check the type of each object's type
for obj in different_objs:
    # Show that the type’s type is always `type`
    assert type(type(obj)) is type
Python

So the type of any Python type is type. If that sounds confusing, it gets even better: the type of the type object is another type. This can be continued forever, like a snake biting its own tail:

# It's `type` all the way down
assert type(type(type(type))) is type
Python

To clear up any confusion, it’s essential to delve deeper into Python’s object-oriented pro­gram­ming (OOP) system. Python’s built-in type object rep­re­sents a so-called metaclass. A metaclass behaves to a class as a class behaves to an object. In other words, a metaclass is a template for a class, while a class is a template for an object:

Template Instance
Class Object
metaclass class
example: type int, str etc.
example:int 42
example: str “Walter White”

How to use the type() function in Python?

Python’s type() function is commonly used to retrieve the type of an object during runtime. This func­tion­al­i­ty is valuable due to Python being a dy­nam­i­cal­ly typed language. In contrast, sta­t­i­cal­ly typed languages like Java require variable types to be declared and cannot be altered during runtime.

// Declare variable as `boolean`
boolean answer;
// Attempting to assign `int` value
// Throws type error
answer = 42;
Java

In contrast, variables in Python are simply names that refer to typed values. At any time during code execution, a name can be ref­er­enced to a value with a different type. So to determine the type of a Python variable at runtime, we need the type() function:

# Assign Boolean value
answer = True
# Show that type is `bool`
assert type(answer) is bool
# Reassign integer value
answer = 42
# Show that type is now `int`
assert type(answer) is int
Python

Checking the type of function arguments in Python

When defining a function, it’s often necessary to check the arguments for com­pli­ance with certain criteria. This includes checking if the arguments fall within certain limits or con­firm­ing that they are of suitable types. By per­form­ing these checks, potential runtime errors can be avoided.

Let’s il­lus­trate the use of the type() function with an example. We’ll define a function that adds up a list of numbers. For this to work, we need to ensure that each argument is a number. We use type() inside an assert statement:

# Function to add up numeric arguments
def add_numbers(*args):
    result = 0
    # Check each argument
    for arg in args:
        # Abort with error message if argument is not an `int` or `float`
        assert type(arg) in (int, float), f"Argument `{arg}` is not a number"
        # Add argument's value to total
        result += arg
    return result
# Show that it works for numbers
assert add_numbers(35, 7) == 42
# The following will fail
add_numbers(29, 'thirteen')
Python

Debugging in Python REPL with the type() function

An advantage of using an in­ter­pret­ed language like Python is the in­ter­ac­tive execution of code in the REPL (Read-Eval-Print-Loop). The approach allows fast pro­to­typ­ing and debugging via in­spec­tion of objects in memory.

Let’s imagine the following scenario. Our code contains a variable answer that is supposed to contain a Boolean value. We find that the type doesn’t match our ex­pec­ta­tions and use Python’s type() function to output the type. As it turns out, we ac­ci­den­tal­ly wrote the Boolean value in quotes – a common mistake, es­pe­cial­ly among beginners:

# Accidentally set to string
answer = 'False'
# Assertion will fail
assert type(answer) is bool
# Correct to Boolean value
answer = False
# Now assertion holds
assert type(answer) is bool
Python

Create Python classes dy­nam­i­cal­ly using the type() function

As shown, Python classes can be created dy­nam­i­cal­ly, i.e. during runtime, using the type() function. This is useful for families of classes, among other things. Let’s demon­strate the concept of class families with an example using HTML tags. First, we create a base class tag where objects of this class can represent them­selves as HTML code.

# Class representing HTML tag
class Tag:
    # Initialize HTML tag with contents
    def __init__(self, *args):
        # Join contents of tag
        self.content = "".join([arg.__str__() for arg in args])
    # String representation returns HTML
    def __str__(self):
        return f"<{self.name}>{self.content}</{self.name}>"
Python

To **spe­cial­ize the base class tag via in­her­i­tance for specific HTML tags like <p> or <h1>we can utilize the type() function again. Let’s il­lus­trate this with an example:

# Create `P` class
P = type('P', (Tag,), {"name": 'p'})
Python
  1. Name of the new class as string.

  2. Tuple with base classes.

    Python allows multiple in­her­i­tance; to derive from only one class, we use the notation (ClassName,).

  3. Dict with the name of the class and ad­di­tion­al entries if necessary.

    The entries can also be functions.

Sub­se­quent­ly, we in­stan­ti­ate a p tag and check that the rep­re­sen­ta­tion works correctly:

# Instantiate `p` tag
greeting = P("Hello world")
assert str(greeting) == '&lt;p&gt;Hello world&lt;/p&gt;'
Python

The same effect can be achieved by analogous class de­f­i­n­i­tion:

# Create `P` class
class P(Tag):
    name = 'p'
Python

As another example, we create classes for headings with type(). Using the dynamic class creation ca­pa­bil­i­ty of type(), we can create classes for all six heading levels at once using list com­pre­hen­sion:

h_1_to_6 = ( f"h{n}" for n in range(1, 7) )
headings = [type(heading, (Tag,), {"name": heading}) for heading in h_1_to_6]
Python

As shown, it’s worth using the type() function to create multiple related sub­class­es. We demon­strate the approach using the more complex example of defining classes for modeling playing cards. First, we define a su­per­class Card using the class keyword:

# Class representing abstract playing card
class Card:
    def __init__(self, number):
        self.number = number
    # String representation
    def __str__(self):
        return f"{self.number} of {self.suite}"
Python

Next, we create sub­class­es for the four map colors using type():

# Create concrete types for each suite
Clubs = type('Clubs', (Card,), {'suite': 'Clubs'})
Diamonds = type('Diamonds', (Card,), {'suite': 'Diamonds'})
Hearts = type('Hearts', (Card,), {'suite': 'Hearts'})
Spades = type('Spades', (Card,), {'suite': 'Spades'})
Python

Now the in­di­vid­ual cards can be in­stan­ti­at­ed:

# Instantiate a 7 of Spades
card = Spades(7)
# Show that it worked
assert str(card) == '7 of Spades'
Python

What are the limits of the type() function?

Python’s type() function is useful. However, there are some cases where the function reaches its limits. For­tu­nate­ly, Python has some workarounds. Let’s look at some of them.

Break down in­her­i­tance hi­er­ar­chies with isin­stance()

type() only de­ter­mines the actual type of a Python object, but ignores the in­her­i­tance hierarchy. Let’s il­lus­trate this dilemma with our playing card example from the last section. The type of a 7 of spades should be both “playing card” and “spade”. However, with type() this cannot be de­ter­mined:

# Create a Seven of Spades
card = Spades(7)
# Our card is a Spade alright
assert type(card) is Spades
# But not a card??
assert type(card) is not Card
Python

To correctly break down the un­der­ly­ing poly­mor­phism, we use the isinstance() function.

# Seven of Spades is a `Spade`
assert isinstance(card, Spades)
# And is also a `Card`
assert isinstance(card, Card)
Python

Simplify Python object type detection with match-case

As shown above, the type() function is often used to determine the type of an object at runtime. To dis­tin­guish several possible types from one another, an if-elif-else construct is used if necessary:

# Determine type of object
if type(obj) is int:
    print("Int")
elif type(obj) is float:
    print("Float")
elif type(obj) is ...:
    print("...")
else:
    print("Something else")
Python

As of version 3.10, however, Python knows the match-case statement. This rec­og­nizes types without calling the type() function.

In a case block, con­struc­tor functions like int(obj) or str(obj) can be used to match the block if the object has the re­spec­tive type.

# Example object
obj = 42
# Determine object type
match obj:
    case int(obj):
        print(f"{obj} is `int`")
    case float(obj):
        print(f"{obj} is `float`")
    case _:
        print(f"{obj} is something else")
Python
Tip

To get started with Python, check out our Python tutorial and our overview of useful Python operators.

Go to Main Menu