Python’s types module exposes built-in type objects and utilities for runtime type work. import types. SimpleNamespace: ns = types.SimpleNamespace(x=1, y=2) → ns.x == 1; settable; vars(ns) → dict; useful as anonymous structs. MappingProxyType: types.MappingProxyType(d) → immutable view of dict d; raises TypeError on mutation. ModuleType: m = types.ModuleType("mymod") — create synthetic module; assign to sys.modules["mymod"] to make importable. FunctionType: types.FunctionType — isinstance check for defs incl. lambdas. MethodType: types.MethodType(fn, instance) — bind a function to an instance. LambdaType: same as FunctionType. CodeType: types.CodeType — code objects from compile() or fn.__code__. GeneratorType / CoroutineType / AsyncGeneratorType — type checks for generators/coroutines. TracebackType: types.TracebackType. FrameType: types.FrameType. BuiltinFunctionType / BuiltinMethodType: isinstance check for C-level callables. NoneType: type(None) = types.NoneType (3.10+). EllipsisType / NotImplementedType (3.10+). new_class: types.new_class(name, bases, kwds, exec_body) — dynamic class with metaclass. DynamicClassAttribute: descriptor that works differently on instances vs classes (used by enum). GenericAlias: list[int] → types.GenericAlias. UnionType: int | str → types.UnionType (3.10+). Claude Code generates plugin systems, configuration namespaces, frozen configs, synthetic modules, and type-safe dispatchers.
CLAUDE.md for types
## types Stack
- Stdlib: import types
- Namespace: ns = types.SimpleNamespace(**d) # attrs instead of dict keys
- Frozen: proxy = types.MappingProxyType(config_dict) # immutable
- Module: m = types.ModuleType("name"); sys.modules["name"] = m
- IsFunc?: isinstance(obj, types.FunctionType)
- IsMeth?: isinstance(obj, types.MethodType)
- IsGen?: isinstance(obj, types.GeneratorType)
types Runtime Type Pipeline
# app/typesutil.py — namespace, proxy, synthetic module, type checks, dispatch
from __future__ import annotations
import sys
import types
from collections.abc import Callable
from dataclasses import asdict, dataclass
from typing import Any, TypeVar
T = TypeVar("T")
# ─────────────────────────────────────────────────────────────────────────────
# 1. SimpleNamespace helpers
# ─────────────────────────────────────────────────────────────────────────────
def namespace(**kwargs: Any) -> types.SimpleNamespace:
"""
Create a SimpleNamespace with the given keyword fields.
Example:
cfg = namespace(host="localhost", port=8080, debug=True)
cfg.port # 8080
"""
return types.SimpleNamespace(**kwargs)
def namespace_from_dict(d: dict[str, Any]) -> types.SimpleNamespace:
"""
Convert a flat dict to a SimpleNamespace.
Example:
ns = namespace_from_dict(config_dict)
print(ns.timeout)
"""
return types.SimpleNamespace(**d)
def namespace_to_dict(ns: types.SimpleNamespace) -> dict[str, Any]:
"""Return a dict copy of a SimpleNamespace."""
return vars(ns).copy()
def merge_namespaces(*namespaces: types.SimpleNamespace) -> types.SimpleNamespace:
"""
Merge multiple SimpleNamespaces left-to-right (later ones override).
Example:
defaults = namespace(timeout=30, retries=3)
overrides = namespace(timeout=60)
cfg = merge_namespaces(defaults, overrides)
cfg.timeout # 60
cfg.retries # 3
"""
merged: dict[str, Any] = {}
for ns in namespaces:
merged.update(vars(ns))
return types.SimpleNamespace(**merged)
def frozen_namespace(**kwargs: Any) -> types.MappingProxyType:
"""
Create a MappingProxyType (immutable dict view) from keyword arguments.
Attempting to set, delete, or modify keys raises TypeError.
Example:
config = frozen_namespace(host="localhost", port=5432)
config["host"] # "localhost"
config["host"] = "x" # TypeError
"""
return types.MappingProxyType(kwargs)
# ─────────────────────────────────────────────────────────────────────────────
# 2. MappingProxyType helpers
# ─────────────────────────────────────────────────────────────────────────────
def freeze(d: dict[str, Any]) -> types.MappingProxyType:
"""
Return an immutable MappingProxyType view of dict d.
The underlying dict is NOT copied — mutations to d will be visible
through the proxy. Use freeze(dict(d)) for a true immutable snapshot.
Example:
proxy = freeze({"endpoints": [...], "version": "1.0"})
"""
return types.MappingProxyType(d)
def frozen_copy(d: dict[str, Any]) -> types.MappingProxyType:
"""
Return a frozen snapshot of d (creates a copy first).
Example:
DEFAULTS = frozen_copy({"timeout": 30, "retries": 3})
"""
return types.MappingProxyType(dict(d))
def is_frozen(obj: Any) -> bool:
"""Return True if obj is a MappingProxyType."""
return isinstance(obj, types.MappingProxyType)
# ─────────────────────────────────────────────────────────────────────────────
# 3. Synthetic module creation
# ─────────────────────────────────────────────────────────────────────────────
def make_module(name: str, doc: str = "", **attrs: Any) -> types.ModuleType:
"""
Create a synthetic module with given attributes.
The module is NOT registered in sys.modules automatically.
Example:
constants = make_module("myapp.constants", TIMEOUT=30, MAX_RETRIES=3)
constants.TIMEOUT # 30
"""
m = types.ModuleType(name, doc)
for k, v in attrs.items():
setattr(m, k, v)
return m
def register_module(module: types.ModuleType) -> types.ModuleType:
"""
Register a module in sys.modules so it is importable.
Example:
constants = make_module("myapp.constants", VERSION="1.0")
register_module(constants)
from myapp.constants import VERSION # works
"""
sys.modules[module.__name__] = module
return module
def ephemeral_module(name: str, code: str) -> types.ModuleType:
"""
Create and execute a module from source code strings.
The module is not registered in sys.modules.
Example:
m = ephemeral_module("calc", "def add(a,b): return a+b")
m.add(1, 2) # 3
"""
m = types.ModuleType(name)
exec(compile(code, f"<ephemeral:{name}>", "exec"), m.__dict__)
return m
# ─────────────────────────────────────────────────────────────────────────────
# 4. Type predicate helpers
# ─────────────────────────────────────────────────────────────────────────────
def is_function(obj: Any) -> bool:
"""True for 'def' functions and lambdas (not bound methods or C callables)."""
return isinstance(obj, types.FunctionType)
def is_method(obj: Any) -> bool:
"""True for bound methods."""
return isinstance(obj, types.MethodType)
def is_builtin(obj: Any) -> bool:
"""True for C-level functions and methods (e.g., len, list.append)."""
return isinstance(obj, (types.BuiltinFunctionType, types.BuiltinMethodType))
def is_generator_fn(obj: Any) -> bool:
"""True if obj is a generator function (uses yield)."""
import inspect
return inspect.isgeneratorfunction(obj)
def is_coroutine_fn(obj: Any) -> bool:
"""True if obj is an async def function."""
import inspect
return inspect.iscoroutinefunction(obj)
def is_generator_obj(obj: Any) -> bool:
"""True if obj is a generator iterator (yielded but not exhausted)."""
return isinstance(obj, types.GeneratorType)
def callable_kind(obj: Any) -> str:
"""
Return a string describing the kind of callable obj is.
Example:
callable_kind(len) # "builtin"
callable_kind(lambda: None) # "function"
callable_kind(str.upper) # "method_descriptor"
callable_kind(MyClass().method) # "method"
"""
if isinstance(obj, types.FunctionType):
return "function"
if isinstance(obj, types.MethodType):
return "method"
if isinstance(obj, (types.BuiltinFunctionType, types.BuiltinMethodType)):
return "builtin"
if isinstance(obj, types.MethodDescriptorType if hasattr(types, "MethodDescriptorType") else object):
return "method_descriptor"
if callable(obj):
return "callable_object"
return "not_callable"
# ─────────────────────────────────────────────────────────────────────────────
# 5. Dynamic method binding
# ─────────────────────────────────────────────────────────────────────────────
def bind_method(fn: Callable, instance: Any) -> types.MethodType:
"""
Bind a function to an instance, creating a bound method.
Example:
class Adder:
pass
def add(self, x):
return x + 1
obj = Adder()
obj.add = bind_method(add, obj)
obj.add(5) # 6
"""
return types.MethodType(fn, instance)
def add_method(cls: type, fn: Callable, name: str | None = None) -> None:
"""
Dynamically add a function to a class as an unbound method.
Example:
class Dog:
pass
def speak(self):
return "Woof!"
add_method(Dog, speak)
Dog().speak() # "Woof!"
"""
setattr(cls, name or fn.__name__, fn)
# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────
if __name__ == "__main__":
print("=== types demo ===")
print("\n--- namespace ---")
cfg = namespace(host="localhost", port=8080, debug=True)
print(f" cfg.host={cfg.host} cfg.port={cfg.port}")
cfg.port = 9000 # mutable
print(f" after mutate: cfg.port={cfg.port}")
print(f" as dict: {namespace_to_dict(cfg)}")
print("\n--- merge_namespaces ---")
defaults = namespace(timeout=30, retries=3, debug=False)
overrides = namespace(timeout=60, debug=True)
merged = merge_namespaces(defaults, overrides)
print(f" merged: timeout={merged.timeout} retries={merged.retries} debug={merged.debug}")
print("\n--- MappingProxyType ---")
CONSTS = frozen_copy({"PI": 3.14159, "E": 2.71828, "MAX": 100})
print(f" CONSTS['PI'] = {CONSTS['PI']}")
print(f" is_frozen: {is_frozen(CONSTS)}")
try:
CONSTS["PI"] = 0 # type: ignore
except TypeError as e:
print(f" mutation blocked: {e}")
print("\n--- make_module / register_module ---")
myconsts = make_module("demo.consts", TIMEOUT=30, VERSION="1.0")
print(f" myconsts.TIMEOUT={myconsts.TIMEOUT} VERSION={myconsts.VERSION}")
register_module(myconsts)
import demo.consts as dc
print(f" imported demo.consts.TIMEOUT={dc.TIMEOUT}")
print("\n--- ephemeral_module ---")
calc = ephemeral_module("calc", "def add(a, b): return a + b\nPI = 3.14")
print(f" calc.add(3, 4) = {calc.add(3, 4)}")
print(f" calc.PI = {calc.PI}")
print("\n--- type predicates ---")
import inspect
async def async_fn(): pass
def gen_fn():
yield 1
print(f" is_function(lambda: None) : {is_function(lambda: None)}")
print(f" is_function(len) : {is_function(len)}")
print(f" is_method(str.upper) : {is_method(str.upper)}")
print(f" is_builtin(len) : {is_builtin(len)}")
print(f" is_coroutine_fn(async_fn) : {is_coroutine_fn(async_fn)}")
print(f" is_generator_fn(gen_fn) : {is_generator_fn(gen_fn)}")
g = gen_fn()
print(f" is_generator_obj(gen_fn()) : {is_generator_obj(g)}")
print("\n--- callable_kind ---")
for obj in [len, print, lambda: None, "".upper, object()]:
try:
print(f" {repr(obj)[:35]:38s}: {callable_kind(obj)}")
except Exception:
pass
print("\n--- bind_method / add_method ---")
class Counter:
def __init__(self):
self.count = 0
def increment(self, by: int = 1) -> None:
self.count += by
add_method(Counter, increment)
c = Counter()
c.increment(5)
c.increment(3)
print(f" counter after two increments: {c.count}")
bound = bind_method(lambda self: self.count * 2, c)
print(f" bound method result: {bound()}")
print("\n=== done ===")
For the dataclasses alternative — @dataclass generates __init__, __repr__, __eq__, and optionally __hash__ and comparison methods for structured data with typed fields; types.SimpleNamespace provides ad-hoc attribute bags without any schema — use @dataclass when the structure is stable and type annotations and validation matter; use SimpleNamespace for quick anonymous grouping of values in tests, scripts, and return values from functions where defining a full class is overkill. For the named_tuple (typing.NamedTuple) alternative — NamedTuple provides immutable, indexable, size-fixed records with named field access and tuple unpacking; SimpleNamespace is mutable, not indexable, and has no length — use NamedTuple for lightweight value objects and return types where immutability, hashing, or tuple interoperability is needed; use SimpleNamespace when fields may be added or changed after construction. The Claude Skills 360 bundle includes types skill sets covering namespace()/namespace_from_dict()/namespace_to_dict()/merge_namespaces() SimpleNamespace helpers, freeze()/frozen_copy()/frozen_namespace()/is_frozen() MappingProxyType utilities, make_module()/register_module()/ephemeral_module() synthetic module creation, is_function()/is_method()/is_builtin()/is_generator_fn()/is_coroutine_fn()/callable_kind() type predicates, and bind_method()/add_method() dynamic binding. Start with the free tier to try runtime type patterns and types module pipeline code generation.