An unfamiliar Python value can leave you unsure what operations it supports. type() reports the value’s class, which defines what its instances can do, or creates a class when called with three arguments.

I’ll walk through both forms of type() and show when to use type() or isinstance().

TL;DR: What Python type() Does

Python type() either returns an object’s class or creates a new class, depending on whether you pass one argument or three.

  • Use type(value) to inspect the exact class at runtime.
  • Use isinstance(value, Base) when subclasses should also count.
  • Use type(name, bases, namespace) for dynamic class creation, not ordinary class definitions.

What Is the Python type() Function?

type() is a built-in that returns the class object associated with a value. For example, type(42) is int and type(“hi”) is str.

A class defines operations for its instances. Classes are objects, and the default class-making machinery is type.

Inheritance means a child instance can also satisfy a parent-class check. The direct class remains the child class.

I use the built-in during debugging when the reported class helps explain the available operations.

Lists allow item assignment, but tuples do not. Their classes define these distinct operations. An object’s identity stays separate from its class, even when a mutable value changes.

Class attributes can be read through an instance. Assigning a value on one instance can shadow the class attribute for that instance.

How to Use Both Forms of type()

Use the one-argument form to inspect a value, then use the three-argument form only when code must create a class from data at runtime. The short program below exercises both forms and an inheritance check.

Step 1: Inspect an object’s class

Call type(value) and read the class name or compare the result to a known class. The exact command used for this example was python3 type_demo.py.

class Animal:
    pass


class Dog(Animal):
    pass


value = Dog()
print(type(42))
print(type(value).__name__)
print(isinstance(value, Animal))

Record = type("Record", (), {"kind": "sample"})
record = Record()
print(type(record).__name__)
print(record.kind)

The output from that execution is:

The first line prints the class object for an integer. The next line uses __name__ to show Dog without the surrounding class representation. isinstance returns True because Dog inherits from Animal.

Step 2: Build a class from a name, bases and namespace

The namespace mapping can contain class attributes or functions that become methods. For example, {“kind”: “sample”} creates the class attribute kind.

For multiple bases, Python searches in its method resolution order. Generated classes follow the same lookup rules as classes declared with class syntax.

The first argument becomes the class name, so choose a stable, descriptive string that makes tracebacks understandable. The returned value is a class object, not an instance. Call that class to create instances, as the example does with Record.

An object that consumes generated classes can inspect their names and declared bases through class attributes. That can help registries report which class was selected without constructing an instance first.

When earlier code assembles attributes, store them in a dictionary before creating the class so the mapping can be checked before it is applied.

Keep the namespace small enough that its generated members are clear when someone inspects the class later.

I ran the file python3 type_demo.py to check the object form and a class made with the three-argument form. Its output showed the new instance’s class name as Record and its class attribute as sample.

An empty bases tuple means the class has no explicitly listed parent. Calling Record() creates an instance, and reading its kind attribute returns sample.

A class statement is clearer when the definition is known in advance. A plugin registry is one example where configuration may determine the class name and members during execution.

This flexibility costs discoverability. To debug a generated class, trace the mapping that supplied its name and attributes rather than looking for a conventional class block.

For a deeper look at instances and classes, see Python classes and objects and the official class creation documentation.

When Should You Use type() or isinstance()?

Use isinstance() when your code accepts a base class, its subclasses or several acceptable classes in a tuple. I use it in the Dog example because the intended contract accepts any Animal, not one concrete class.

For example, bool inherits from int. True therefore passes an isinstance() check for int, even though its exact class is bool. Use an exact comparison only when that distinction changes the behavior you want.

Question Use Reason
What is the exact class? type(value) Returns the direct class object.
Is this an instance of a class or subclass? isinstance(value, Base) Accounts for inheritance.
Must this be exactly one class? type(value) is Expected Requires exact class identity.
What class should code create at runtime? type(name, bases, namespace) Constructs a class object from those inputs.

Unlike a converter, this function only inspects a value. int(“4”) converts text to an integer, while inspecting that text reports str. The class of None has the special name NoneType.

Python does not enforce function annotations during calls. Type hints instead inform static checkers and editors, as the typing documentation explains.

The three-argument form requires a string name, a tuple of base classes and a namespace mapping. Custom metaclasses add class-creation behavior beyond this basic form.

Common type() Mistakes and What to Do Next

The one-argument and three-argument forms solve different tasks, so matching the call shape to your goal avoids confusing a class lookup with class creation.

print(type(42).__name__)
print(type("Record", (), {}).__name__)
Case Symptom Fix
Passing multiple arguments to inspect a value Python treats the call as a request to create a class, and required arguments may be missing. Use type(value) for inspection.
Expecting type(value) to include subclasses An exact class comparison rejects a child class. Use isinstance(value, Base) when subclasses are valid.
Using type() as input validation The check describes a current class but does not establish that a value meets the program’s full contract. Validate the allowed values and behavior your function requires.

For the next check, run the example file again after changing Dog’s parent and compare the direct class name with the isinstance result. That shows which parts of your code depend on exact class identity.

Conclusion: Choose the Type Check That Fits

Keep inspection separate from conversion and input validation. A type check describes the object, while your program’s contract decides what values it accepts.

For the full object model, use Python’s data model reference.

FAQ

These short answers cover the distinctions that commonly come up when inspecting Python values.

What does type() return in Python?

With one argument, type(object) returns the object’s exact class object. With three arguments, it creates and returns a new class object.

Should I use type() or isinstance()?

Use isinstance() when subclasses should also count. Use type(value) is Expected only when the exact class is required.

Does type() convert a value?

No. type(value) reports the value’s class. A conversion such as int(‘4’) creates a value of another type.

Share.
Leave A Reply