Python types Module

In this guide, you'll explore Python's types module, which provides names for built-in type objects. Learn its features and examples for dynamic programming.

The types module in Python defines names for various object types that are used internally by the interpreter. This module is particularly useful when you need to perform type checking or create new types dynamically.

Table of Contents

  1. Introduction
  2. Key Classes and Types
    • MappingProxyType
    • SimpleNamespace
    • DynamicClassAttribute
    • GeneratorType
    • CoroutineType
    • AsyncGeneratorType
    • CodeType
    • FunctionType
    • LambdaType
    • MethodType
    • BuiltinFunctionType
    • BuiltinMethodType
    • ModuleType
  3. Examples
    • Using MappingProxyType
    • Using SimpleNamespace
    • Using DynamicClassAttribute
  4. Real-World Use Case
  5. Conclusion
  6. References

Introduction

The types module provides a standard interface for type-related operations. It includes definitions for many of the types that the Python interpreter uses internally, making it useful for type checking and dynamic type creation.

Key Classes and Types

MappingProxyType

A wrapper for read-only dictionaries.

from types import MappingProxyType

writable = {'key1': 'value1'}
read_only = MappingProxyType(writable)

print(read_only['key1'])
# read_only['key1'] = 'new_value'  # This will raise a TypeError

Output:

value1

SimpleNamespace

A simple object subclass that provides attribute access to its namespace.

from types import SimpleNamespace

ns = SimpleNamespace(x=10, y=20)
print(ns.x, ns.y)
ns.z = 30
print(ns.z)

Output:

10 20
30

DynamicClassAttribute

An attribute to support computed attributes in extension types.

from types import DynamicClassAttribute

class MyClass:
    def __init__(self, value):
        self._value = value
    
    @DynamicClassAttribute
    def value(self):
        return self._value

obj = MyClass(10)
print(obj.value)

Output:

10

GeneratorType

The type of generator-iterator objects, such as those created by generator functions.

from types import GeneratorType

def generator():
    yield 1
    yield 2

gen = generator()
print(isinstance(gen, GeneratorType))

Output:

True

CoroutineType

The type of coroutine objects, such as those created by async functions.

from types import CoroutineType

async def coroutine():
    await asyncio.sleep(1)

coro = coroutine()
print(isinstance(coro, CoroutineType))

Output:

True
sys:1: RuntimeWarning: coroutine 'coroutine' was never awaited

AsyncGeneratorType

The type of asynchronous generator objects.

from types import AsyncGeneratorType

async def async_generator():
    yield 1
    yield 2

agen = async_generator()
print(isinstance(agen, AsyncGeneratorType))

Output:

True

CodeType

The type for code objects, such as those returned by compile().

from types import CodeType

code = compile('print("Hello, World!")', '<string>', 'exec')
print(isinstance(code, CodeType))

Output:

True

FunctionType

The type for user-defined functions.

from types import FunctionType

def func():
    pass

print(isinstance(func, FunctionType))

Output:

True

LambdaType

The type for lambda functions. It is the same as FunctionType.

from types import LambdaType

lambda_func = lambda x: x
print(isinstance(lambda_func, LambdaType))

Output:

True

MethodType

The type for bound and unbound methods of class instances.

from types import MethodType

class MyClass:
    def method(self):
        pass

obj = MyClass()
print(isinstance(obj.method, MethodType))

Output:

True

BuiltinFunctionType

The type for built-in functions.

from types import BuiltinFunctionType

print(isinstance(len, BuiltinFunctionType))

Output:

True

BuiltinMethodType

The type for built-in methods of classes.

from types import BuiltinMethodType

print(isinstance([].append, BuiltinMethodType))

Output:

True

ModuleType

The type for modules.

import types
import sys

print(isinstance(sys, types.ModuleType))

Output:

True

Examples

Using MappingProxyType

from types import MappingProxyType

writable = {'key1': 'value1'}
read_only = MappingProxyType(writable)

print(read_only['key1'])  # Outputs: value1
writable['key1'] = 'new_value'
print(read_only['key1'])  # Outputs: new_value

try:
    read_only['key1'] = 'another_value'  # Raises TypeError
except TypeError as e:
    print(e)

Output:

value1
new_value
'mappingproxy' object does not support item assignment

Using SimpleNamespace

from types import SimpleNamespace

ns = SimpleNamespace(a=1, b=2)
print(ns.a, ns.b)  # Outputs: 1 2
ns.c = 3
print(ns.c)  # Outputs: 3
print(ns)  # Outputs: namespace(a=1, b=2, c=3)

Output:

1 2
3
namespace(a=1, b=2, c=3)

Using DynamicClassAttribute

from types import DynamicClassAttribute

class MyClass:
    def __init__(self, value):
        self._value = value
    
    @DynamicClassAttribute
    def value(self):
        return self._value

obj = MyClass(10)
print(obj.value)  # Outputs: 10

Output:

10

Real-World Use Case

Creating Dynamic Types

The types module can be used to create dynamic types at runtime, which is useful for metaprogramming and frameworks that need to generate classes dynamically.

import types

def make_class(name, base_classes, attrs):
    return types.new_class(name, base_classes, exec_body=lambda ns: ns.update(attrs))

attrs = {'x': 1, 'y': 2, 'method': lambda self: self.x + self.y}
NewClass = make_class('NewClass', (object,), attrs)

instance = NewClass()
print(instance.method())  # Outputs: 3

Output:

3

Conclusion

The types module in Python provides a variety of type definitions that are useful for type checking and dynamic type creation. It supports a wide range of types used internally by the Python interpreter, making it used for advanced programming tasks.

References

Comments

Spring Boot 3 Paid Course Published for Free
on my Java Guides YouTube Channel

Subscribe to my YouTube Channel (165K+ subscribers):
Java Guides Channel

Top 10 My Udemy Courses with Huge Discount:
Udemy Courses - Ramesh Fadatare