type in Python: finding out what a value is

type reveals the exact nature of a Python value. A diagnosis tool, to be told apart from isinstance, which is the one that decides.
5 min read
Believemy logo

Definition

A value arrives in code with no label attached. It comes from a file, a keyboard prompt, or the return of a function someone else wrote, and nothing shows at a glance whether it behaves like a number, a piece of text or a list. As long as that nature stays uncertain, an operation that looks harmless can fail, or worse, succeed while handing back a wrong result. type answers that uncertainty: called with a value, the function hands back the class it belongs to, which is enough to settle the question without guessing or reading back through the code that produced it.

Three examples are enough to see the function at work, on a number, a piece of text and a list:

PYTHON
print(type(7))
# <class 'int'>

print(type("7"))
# <class 'str'>

print(type([7]))
# <class 'list'>

What comes back is not text but a full object, the class itself. That distinction has a concrete consequence: type(7) is int is True, because the comparison is made on two objects that are identical in memory, not on two words that merely look alike on the page.


The types met every day

An error message almost always mentions one of these names in passing, NoneType, dict, str. Recognising it on sight saves a trip to look up its meaning. The table below gathers the types that show up most often in ordinary Python code, with what each one stands for.

ValueType returnedWhat it stands for
42intA whole number, to count and measure
3.5floatA float, with decimals
"hello"strA string of characters
[1, 2]listA changeable list
(1, 2)tupleA frozen sequence
{"a": 1}dictA dictionary, read by key
TrueboolA bool, true or false
NoneNoneTypeThe absence of a value, None

The table also reads backwards: each of these names is at the same time a building function. int("42") turns text into a number, str(42) does the reverse, and list("abc") breaks a string apart into a list of characters. One family of words is enough to both identify a value and produce one.


Diagnose instead of guessing

In shipped code, this function rarely serves to write a condition. Its ground is the moment a computation returns a result that makes no sense. The useful reflex is then to look at the exact nature of the values involved, because the error Python reports often arrives several lines after the point where the problem was born, on an operation that has nothing to do with it.

The following situation comes up constantly for anyone starting out:

PYTHON
quantity = input("How many? ")
print(type(quantity))
# <class 'str'>

total = quantity * 3
# "222" instead of 6

The culprit here is input, which always hands back text, even when the person types digits. The multiplication does not crash, it repeats the string three times, and the fault spreads in silence all the way to the final display. A call to type dropped right after the input settles the question in a second, where reading back through the whole computation can take an hour.


Observe with type, decide with isinstance

One question remains: how to steer a treatment according to the nature of a value? Despite the temptation, that is not the role of type. The right tool to decide is isinstance, because it takes inheritance into account where the strict comparison ignores it completely.

The difference shows up on a class that inherits from an existing type, such as a basket inheriting from a dictionary:

PYTHON
class Basket(dict):
    pass

b = Basket()

isinstance(b, dict)   # True
type(b) is dict       # False

An object derived from a class is still an instance of its parent class, whereas its exact type has changed, which is why the two lines do not give the same answer.

Warning

bool inherits from int in Python. isinstance(True, int) is therefore True, which trips up anyone testing a value while believing they exclude booleans: a True slipped into a list of numbers passes the test unnoticed.

In practice, this function is there to observe while working the code out, while isinstance is there to decide once the code ships. It also accepts several candidates at once, as in isinstance(value, (int, float)), which covers both numeric families inside a single condition.


Frequently asked questions

Question

How can the name of the type alone be obtained?

By reading the __name__ attribute of the returned class: type(value).__name__ gives the string "int" rather than the full representation between angle brackets. That is the form to favour in an error message meant to be read by someone.

Question

What does this function do when called with three arguments?

It no longer reads an existing type, it creates a new one: type("Point", (), {}) builds a class named Point, with no parent or content. That form serves code generating classes on the fly, and is a reminder that in Python a class is a value like any other.

Question

Should the nature of every incoming argument be checked?

No, the culture of the language prefers trying first and catching afterwards with try rather than checking before acting. Systematic checking weighs the code down and sometimes turns away values that would have behaved perfectly well. A check keeps its value at the borders of the program, on data coming from a file or from the network. Understanding when Python converts on its own and when it refuses avoids half of the beginner errors, ground our Python course covers.

Related terms

Discover our python glossary

Browse the terms and definitions most commonly used in development with Python.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.