ZetCode

Python type Function

Last modified April 11, 2025

This comprehensive guide explores Python's type function, which returns the type of an object or creates new types. We'll cover type checking, dynamic class creation, and practical examples of type introspection.

Basic Definitions

The type function serves two purposes: it returns an object's type when called with one argument, or creates a new type when called with three arguments.

Key characteristics: returns a type object (same as obj.__class__). With three arguments, it dynamically creates new classes. All Python classes are instances of type.

Basic Type Checking

Here's simple usage showing how type identifies different Python objects. This is the most common single-argument usage.

basic_type.py
# Built-in types
print(type(42))         # <class 'int'>
print(type(3.14))       # <class 'float'>
print(type("hello"))    # <class 'str'>
print(type([1, 2, 3]))  # <class 'list'>
print(type(True))       # <class 'bool'>

# Custom class
class MyClass:
    pass

obj = MyClass()
print(type(obj))        # <class '__main__.MyClass'>

This example shows type returning class objects for built-in types and custom classes. The output format is <class 'typename'>.

For custom classes, the module name (__main__ here) is included in the type name. This helps distinguish between same-named classes.

Type Comparison

type can be used to check an object's exact type, though isinstance() is often preferred for inheritance checks.

type_comparison.py
value = 3.14

# Exact type checking
if type(value) == float:
    print("It's a float")  # Prints

# Not recommended for inheritance cases
class Parent: pass
class Child(Parent): pass

obj = Child()
print(type(obj) == Parent)  # False
print(isinstance(obj, Parent))  # True

This shows type for exact type matching. It won't match parent classes, unlike isinstance which respects inheritance.

Use type when you need the exact class, and isinstance when you want to include subclasses in the check.

Dynamic Class Creation

The three-argument form of type creates new classes dynamically. This is how Python creates classes under the hood.

dynamic_class.py
# Equivalent to: class Person: pass
Person = type('Person', (), {})

# With attributes and methods
def greet(self):
    return f"Hello, {self.name}"

Person = type('Person', (), {
    '__init__': lambda self, name: setattr(self, 'name', name),
    'greet': greet
})

p = Person("Alice")
print(p.greet())  # Hello, Alice
print(type(p))    # <class '__main__.Person'>

This demonstrates dynamic class creation. The three arguments are: class name, base classes tuple, and namespace dictionary containing attributes/methods.

This is how Python's class statement works internally - it calls type to create the class object.

Metaclass Usage

type is the default metaclass in Python. All classes are instances of type, and you can subclass type to create custom metaclasses.

metaclass.py
class Meta(type):
    def __new__(cls, name, bases, namespace):
        print(f"Creating class {name}")
        return super().__new__(cls, name, bases, namespace)

class MyClass(metaclass=Meta):
    pass

# Output: Creating class MyClass
print(type(MyClass))  # <class '__main__.Meta'>

This shows a custom metaclass inheriting from type. The metaclass can modify class creation. Note how type(MyClass) shows the metaclass.

Metaclasses are advanced Python features that allow deep customization of class creation behavior.

Type vs isinstance

This example contrasts type and isinstance to show when each is appropriate.

type_vs_isinstance.py
class Animal: pass
class Dog(Animal): pass

d = Dog()

# type checks exact class
print(type(d) == Dog)      # True
print(type(d) == Animal)   # False

# isinstance checks inheritance
print(isinstance(d, Dog))   # True
print(isinstance(d, Animal)) # True

# Checking against multiple types
print(isinstance(d, (Dog, str, list)))  # True

type checks for exact class matches, while isinstance checks the entire inheritance chain. isinstance also supports checking against multiple types.

Generally prefer isinstance unless you specifically need to exclude subclasses.

Best Practices

Source References

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Python tutorials.