Advanced Python Programming
Deep Dive into Metaclasses and Class Creation
Theory & Concepts
Introduction to Metaclasses
Metaclasses are one of Python's most powerful and misunderstood features. They allow you to control how classes themselves are created, going beyond what decorators and inheritance can achieve.
What Are Metaclasses?
💡 Core Concept: In Python, everything is an object - including classes. Metaclasses are the "classes of classes" - they define how classes behave.
The Type Hierarchy:
object → instance of → class → instance of → metaclass → instance of → typeWhen you write:
class MyClass: passPython actually does:
- Looks for a metaclass (defaults to
type) - Calls the metaclass to create the class
- The metaclass returns the new class object
Why Learn Metaclasses?
Real-World Applications:
- ORM Frameworks: Django and SQLAlchemy use metaclasses to map classes to database tables
- Validation Frameworks: Pydantic uses metaclasses for data validation
- API Frameworks: FastAPI uses metaclasses for automatic serialization
- Singleton Pattern: Enforcing single instance classes
- Plugin Systems: Automatic registration of plugins
- Abstract Base Classes: The
abcmodule uses metaclasses
⚠️ Important: Tim Peters (Python core developer) said: "Metaclasses are deeper magic than 99% of users should ever worry about. If you wonder whether you need them, you don't."
However, understanding metaclasses makes you a better Python developer and helps you understand how frameworks work under the hood.
Understanding type - The Default Metaclass
The built-in type is the default metaclass for all classes in Python.
type as a Function (Runtime Class Creation)
type can be used in two ways:
1. Get the type of an object:
x = 5print(type(x)) # <class 'int'>2. Create a class dynamically:
# type(name, bases, dict)MyClass = type('MyClass', (), {'x': 5})# Equivalent to:class MyClass: x = 5How Classes Are Created
When Python encounters a class definition, it:
- Collects the class body into a dictionary
- Determines the metaclass (
typeby default) - Calls the metaclass with (name, bases, namespace)
- Returns the class object
# These are equivalent:# Traditional syntaxclass Dog: def bark(self): return "Woof!"# Using type directlyDog = type('Dog', (), { 'bark': lambda self: "Woof!"})Creating Custom Metaclasses
A metaclass is a class that inherits from type and overrides specific methods.
The Metaclass Lifecycle
Key methods to override:
-
__new__(mcs, name, bases, namespace)- Called to create the class object
- Can modify class attributes before creation
- Must return the class object
-
__init__(cls, name, bases, namespace)- Called to initialize the class object
- Can't change the class structure
- Used for validation and setup
-
__call__(cls, *args, **kwargs)- Called when the class is instantiated
- Controls how instances are created
- Useful for singletons and object pools
Basic Metaclass Example
class Meta(type): def __new__(mcs, name, bases, namespace): print(f"Creating class {name}") return super().__new__(mcs, name, bases, namespace) def __init__(cls, name, bases, namespace): print(f"Initializing class {name}") super().__init__(name, bases, namespace)class MyClass(metaclass=Meta): pass# Output when class is defined:# Creating class MyClass# Initializing class MyClassPractical Metaclass Patterns
1. Automatic Registration Pattern
Register all subclasses automatically:
class PluginRegistry(type): plugins = [] def __new__(mcs, name, bases, namespace): cls = super().__new__(mcs, name, bases, namespace) if name != 'Plugin': # Don't register base class mcs.plugins.append(cls) return clsclass Plugin(metaclass=PluginRegistry): passclass PDFPlugin(Plugin): passclass ImagePlugin(Plugin): passprint(PluginRegistry.plugins)# [<class 'PDFPlugin'>, <class 'ImagePlugin'>]2. Singleton Pattern
Ensure only one instance exists:
class SingletonMeta(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: instance = super().__call__(*args, **kwargs) cls._instances[cls] = instance return cls._instances[cls]class Database(metaclass=SingletonMeta): def __init__(self): self.connection = "Connected"db1 = Database()db2 = Database()print(db1 is db2) # True - same instance3. Validation and Enforcement
Enforce class structure rules:
class RequiredMethodsMeta(type): required_methods = ['save', 'load'] def __new__(mcs, name, bases, namespace): # Skip validation for base class if name != 'Model': for method in mcs.required_methods: if method not in namespace: raise TypeError( f"Class {name} must implement '{method}' method" ) return super().__new__(mcs, name, bases, namespace)class Model(metaclass=RequiredMethodsMeta): passclass UserModel(Model): def save(self): print("Saving user...") def load(self): print("Loading user...")# This would raise TypeError:# class BrokenModel(Model):# pass # Missing save() and load()4. Automatic Property Creation
Convert attributes to properties automatically:
class AutoPropertyMeta(type): def __new__(mcs, name, bases, namespace): # Find attributes that should be properties for attr_name, attr_value in list(namespace.items()): if not attr_name.startswith('_') and not callable(attr_value): # Create private attribute private_name = f'_{attr_name}' namespace[private_name] = attr_value # Create property namespace[attr_name] = property( lambda self, n=private_name: getattr(self, n), lambda self, value, n=private_name: setattr(self, n, value) ) return super().__new__(mcs, name, bases, namespace)class Person(metaclass=AutoPropertyMeta): name = "" age = 0p = Person()p.name = "Alice"print(p.name) # Works as a property5. ORM-Style Field Validation
Similar to Django/SQLAlchemy:
class Field: def __init__(self, field_type): self.field_type = field_type def validate(self, value): if not isinstance(value, self.field_type): raise TypeError( f"Expected {self.field_type.__name__}, " f"got {type(value).__name__}" )class ModelMeta(type): def __new__(mcs, name, bases, namespace): # Collect field definitions fields = {} for key, value in list(namespace.items()): if isinstance(value, Field): fields[key] = value namespace['_fields'] = fields # Create __init__ that validates fields def __init__(self, **kwargs): for field_name, field in self._fields.items(): value = kwargs.get(field_name) if value is not None: field.validate(value) setattr(self, field_name, value) namespace['__init__'] = __init__ return super().__new__(mcs, name, bases, namespace)class User(metaclass=ModelMeta): name = Field(str) age = Field(int)user = User(name="Alice", age=30)print(user.name, user.age) # Alice 30# This would raise TypeError:# user = User(name="Bob", age="thirty")Advanced Metaclass Concepts
Metaclass Inheritance
Metaclasses can inherit from each other:
class BaseMeta(type): def __new__(mcs, name, bases, namespace): namespace['created_by'] = 'BaseMeta' return super().__new__(mcs, name, bases, namespace)class ExtendedMeta(BaseMeta): def __new__(mcs, name, bases, namespace): namespace['extended_by'] = 'ExtendedMeta' return super().__new__(mcs, name, bases, namespace)class MyClass(metaclass=ExtendedMeta): passprint(MyClass.created_by) # BaseMetaprint(MyClass.extended_by) # ExtendedMetaMultiple Metaclasses (Metaclass Conflict)
When inheriting from classes with different metaclasses, Python requires a common metaclass:
class Meta1(type): passclass Meta2(type): passclass A(metaclass=Meta1): passclass B(metaclass=Meta2): pass# This causes metaclass conflict:# class C(A, B):# pass# Solution: Create a metaclass that inherits from bothclass Meta3(Meta1, Meta2): passclass C(A, B, metaclass=Meta3): pass__prepare__ Method
Controls the namespace dictionary used for the class:
class OrderedMeta(type): @classmethod def __prepare__(mcs, name, bases): # Return OrderedDict to preserve attribute order from collections import OrderedDict return OrderedDict() def __new__(mcs, name, bases, namespace): # namespace is now an OrderedDict print(f"Attributes in order: {list(namespace.keys())}") return super().__new__(mcs, name, bases, dict(namespace))class MyClass(metaclass=OrderedMeta): z = 1 a = 2 m = 3# Output: Attributes in order: ['__module__', '__qualname__', 'z', 'a', 'm']Metaclasses vs Alternatives
When to Use Each Approach
| Pattern | Use When | Example |
|---------|----------|---------|
| Metaclass | Need to control class creation itself | ORM models, ABCs, singletons |
| Class Decorator | Need to modify class after creation | Adding methods, wrapping |
| __init_subclass__ | Need to customize subclasses (Python 3.6+) | Simpler than metaclasses |
| Descriptor | Need to control attribute access | Properties, validators |
__init_subclass__ Alternative (Simpler!)
Python 3.6+ introduced a simpler alternative for many metaclass use cases:
class PluginBase: plugins = [] def __init_subclass__(cls, **kwargs): super().__init_subclass__(**kwargs) cls.plugins.append(cls)class PDFPlugin(PluginBase): passclass ImagePlugin(PluginBase): passprint(PluginBase.plugins)# [<class 'PDFPlugin'>, <class 'ImagePlugin'>]Class Decorators Alternative
For post-creation modification:
def add_timestamp(cls): cls.created_at = datetime.now() return cls@add_timestampclass MyClass: passprint(MyClass.created_at)Common Metaclass Pitfalls
Mistake 1: Overcomplicating Simple Tasks
# ❌ Wrong - Metaclass overkillclass AddMethodMeta(type): def __new__(mcs, name, bases, namespace): namespace['get_name'] = lambda self: self.name return super().__new__(mcs, name, bases, namespace)# ✅ Correct - Use class decorator or inheritancedef add_get_name(cls): cls.get_name = lambda self: self.name return clsMistake 2: Modifying __init__ Instead of __new__
# ❌ Wrong - Can't change class structure in __init__class WrongMeta(type): def __init__(cls, name, bases, namespace): cls.new_attr = "value" # Too late! super().__init__(name, bases, namespace)# ✅ Correct - Modify in __new__class RightMeta(type): def __new__(mcs, name, bases, namespace): namespace['new_attr'] = "value" return super().__new__(mcs, name, bases, namespace)Mistake 3: Not Calling super()
# ❌ Wrong - Breaks inheritance chainclass BadMeta(type): def __new__(mcs, name, bases, namespace): return type.__new__(mcs, name, bases, namespace) # Skip super()# ✅ Correct - Always use super()class GoodMeta(type): def __new__(mcs, name, bases, namespace): return super().__new__(mcs, name, bases, namespace)Real-World Example: Building a Simple ORM
Let's build a mini ORM to understand how Django/SQLAlchemy work:
class Field: def __init__(self, field_type, required=True): self.field_type = field_type self.required = requiredclass ModelMeta(type): def __new__(mcs, name, bases, namespace): # Skip for base Model class if name == 'Model': return super().__new__(mcs, name, bases, namespace) # Collect fields fields = {} for key, value in list(namespace.items()): if isinstance(value, Field): fields[key] = value del namespace[key] # Remove field descriptors namespace['_fields'] = fields namespace['_table_name'] = name.lower() # Add save method def save(self): field_values = { name: getattr(self, name, None) for name in self._fields } print(f"INSERT INTO {self._table_name} {field_values}") namespace['save'] = save return super().__new__(mcs, name, bases, namespace)class Model(metaclass=ModelMeta): def __init__(self, **kwargs): for name, field in self._fields.items(): value = kwargs.get(name) if value is None and field.required: raise ValueError(f"{name} is required") setattr(self, name, value)class User(Model): name = Field(str) email = Field(str) age = Field(int, required=False)user = User(name="Alice", email="alice@example.com")user.save()# Output: INSERT INTO user {'name': 'Alice', 'email': 'alice@example.com', 'age': None}Summary
Key Takeaways:
- Metaclasses control how classes are created, not instances
typeis the default metaclass for all classes- Three key methods:
__new__,__init__,__call__ - Use cases: ORMs, validation, singletons, plugin systems
- Alternatives:
__init_subclass__, decorators, descriptors - Best practice: Use simpler alternatives when possible
Metaclass Workflow:
- Python collects class body → dictionary
- Determines metaclass (explicit or inherited)
- Calls
metaclass.__new__()to create class - Calls
metaclass.__init__()to initialize class - Returns class object
When to Use Metaclasses:
- ✅ Building frameworks (ORMs, APIs)
- ✅ Enforcing API contracts
- ✅ Automatic registration
- ✅ Class-level validation
- ❌ Simple attribute addition (use decorators)
- ❌ Instance behavior (use
__init__)
Best Practices:
- Always call
super()in metaclass methods - Use
__init_subclass__for simpler cases (Python 3.6+) - Document metaclass behavior clearly
- Provide good error messages
- Consider if a decorator would work instead
💡 Final Tip: Master metaclasses to understand Python deeply, but use them sparingly in production code. Most problems have simpler solutions!
Lesson Content
Master Python's metaclasses and understand how classes are created at runtime. Learn to control class instantiation, customize attribute access, and implement powerful metaprogramming patterns.
Code Example
"""Deep Dive into Metaclasses and Class CreationThis module demonstrates advanced metaclass concepts with production-ready examples.Metaclasses control how classes are created - they are the "classes of classes"."""from typing import Dict, Any, Type, Listfrom abc import ABCMetafrom datetime import datetimefrom collections import OrderedDict# ============================================# PART 1: UNDERSTANDING TYPE AND CLASS CREATION# ============================================def demonstrate_type_as_factory(): """Show how type() creates classes dynamically.""" print("="*60) print("PART 1: Creating Classes with type()") print("="*60) # Method 1: Traditional class definition class Dog: species = "Canis familiaris" def __init__(self, name): self.name = name def bark(self): return f"{self.name} says Woof!" # Method 2: Using type() - equivalent to above def bark_method(self): return f"{self.name} says Woof!" DogDynamic = type( 'DogDynamic', # Class name (), # Base classes (tuple) { # Class namespace (dict) 'species': 'Canis familiaris', '__init__': lambda self, name: setattr(self, 'name', name), 'bark': bark_method } ) # Both work identically dog1 = Dog("Buddy") dog2 = DogDynamic("Max") print(f"Traditional: {dog1.bark()}") print(f"Dynamic: {dog2.bark()}") print(f"Both are classes: {type(dog1).__name__}, {type(dog2).__name__}")# ============================================# PART 2: BASIC METACLASS# ============================================class DebugMeta(type): """Metaclass that logs class creation process.""" def __new__(mcs, name, bases, namespace): """ Called to CREATE the class object. Args: mcs: The metaclass itself name: Name of the class being created bases: Tuple of base classes namespace: Dictionary of class attributes """ print(f"[DebugMeta.__new__] Creating class: {name}") print(f" Bases: {bases}") print(f" Attributes: {list(namespace.keys())}") # Create the class cls = super().__new__(mcs, name, bases, namespace) # Add timestamp to all classes cls._created_at = datetime.now() return cls def __init__(cls, name, bases, namespace): """ Called to INITIALIZE the class object. Args: cls: The class that was just created name: Name of the class bases: Tuple of base classes namespace: Dictionary of class attributes """ print(f"[DebugMeta.__init__] Initializing class: {name}") super().__init__(name, bases, namespace) def __call__(cls, *args, **kwargs): """ Called when the class is INSTANTIATED. Args: cls: The class being instantiated *args, **kwargs: Arguments passed to __init__ """ print(f"[DebugMeta.__call__] Creating instance of {cls.__name__}") instance = super().__call__(*args, **kwargs) print(f"[DebugMeta.__call__] Instance created: {instance}") return instanceclass DebuggedClass(metaclass=DebugMeta): """A class using the debug metaclass.""" def __init__(self, value): self.value = value def __repr__(self): return f"DebuggedClass(value={self.value})"# ============================================# PART 3: SINGLETON PATTERN WITH METACLASS# ============================================class SingletonMeta(type): """ Metaclass that implements the Singleton pattern. Ensures only one instance of a class exists. """ _instances: Dict[Type, Any] = {} def __call__(cls, *args, **kwargs): """Return existing instance or create new one.""" if cls not in cls._instances: # Create new instance instance = super().__call__(*args, **kwargs) cls._instances[cls] = instance print(f"Created new {cls.__name__} instance") else: print(f"Returning existing {cls.__name__} instance") return cls._instances[cls]class DatabaseConnection(metaclass=SingletonMeta): """Database connection that should be singleton.""" def __init__(self, host="localhost", port=5432): self.host = host self.port = port print(f"Connecting to {host}:{port}...") def query(self, sql): return f"Executing: {sql}"# ============================================# PART 4: AUTOMATIC PLUGIN REGISTRATION# ============================================class PluginRegistry(type): """ Metaclass that automatically registers all plugin classes. Useful for plugin systems and frameworks. """ plugins: List[Type] = [] def __new__(mcs, name, bases, namespace): cls = super().__new__(mcs, name, bases, namespace) # Register plugin (skip base class) if name != 'Plugin': mcs.plugins.append(cls) print(f"Registered plugin: {name}") return cls @classmethod def get_plugins(mcs): """Return all registered plugins.""" return mcs.plugins @classmethod def get_plugin(mcs, name): """Get plugin by name.""" for plugin in mcs.plugins: if plugin.__name__ == name: return plugin return Noneclass Plugin(metaclass=PluginRegistry): """Base class for all plugins.""" def execute(self): raise NotImplementedErrorclass PDFExportPlugin(Plugin): """Plugin for exporting to PDF.""" def execute(self): return "Exporting to PDF..."class CSVExportPlugin(Plugin): """Plugin for exporting to CSV.""" def execute(self): return "Exporting to CSV..."class ImageProcessorPlugin(Plugin): """Plugin for processing images.""" def execute(self): return "Processing images..."# ============================================# PART 5: VALIDATION AND ENFORCEMENT# ============================================class InterfaceEnforcerMeta(type): """ Metaclass that enforces interface implementation. Similar to abstract base classes but with custom logic. """ required_methods = ['save', 'load', 'validate'] def __new__(mcs, name, bases, namespace): # Skip validation for base class if name == 'Model': return super().__new__(mcs, name, bases, namespace) # Check for required methods missing_methods = [] for method in mcs.required_methods: if method not in namespace: # Check if method is in base classes has_method = any(hasattr(base, method) for base in bases) if not has_method: missing_methods.append(method) if missing_methods: raise TypeError( f"Class '{name}' must implement these methods: " f"{', '.join(missing_methods)}" ) return super().__new__(mcs, name, bases, namespace)class Model(metaclass=InterfaceEnforcerMeta): """Base model class with required interface.""" passclass UserModel(Model): """User model with all required methods.""" def __init__(self, name, email): self.name = name self.email = email def save(self): print(f"Saving user: {self.name}") def load(self): print(f"Loading user: {self.name}") def validate(self): if '@' not in self.email: raise ValueError("Invalid email") print(f"User {self.name} is valid")# ============================================# PART 6: ORM-STYLE FIELD VALIDATION# ============================================class Field: """Base field class for ORM.""" def __init__(self, field_type, required=True, default=None): self.field_type = field_type self.required = required self.default = default def validate(self, value): """Validate field value.""" if value is None: if self.required: raise ValueError(f"Field is required") return self.default if not isinstance(value, self.field_type): raise TypeError( f"Expected {self.field_type.__name__}, " f"got {type(value).__name__}" ) return valueclass ORMMeta(type): """ Metaclass for ORM models. Automatically handles field validation and provides ORM functionality. """ def __new__(mcs, name, bases, namespace): # Skip for base class if name == 'ORMModel': return super().__new__(mcs, name, bases, namespace) # Collect field definitions fields = {} for key, value in list(namespace.items()): if isinstance(value, Field): fields[key] = value # Remove field descriptors from class del namespace[key] namespace['_fields'] = fields namespace['_table_name'] = name.lower() # Create custom __init__ def __init__(self, **kwargs): """Initialize model with field validation.""" for field_name, field in self._fields.items(): value = kwargs.get(field_name) validated_value = field.validate(value) setattr(self, field_name, validated_value) namespace['__init__'] = __init__ # Add ORM methods def save(self): """Save model to database (simulated).""" field_values = { name: getattr(self, name, None) for name in self._fields } print(f"INSERT INTO {self._table_name} {field_values}") def to_dict(self): """Convert model to dictionary.""" return { name: getattr(self, name, None) for name in self._fields } namespace['save'] = save namespace['to_dict'] = to_dict return super().__new__(mcs, name, bases, namespace)class ORMModel(metaclass=ORMMeta): """Base class for ORM models.""" passclass User(ORMModel): """User ORM model with field validation.""" name = Field(str) email = Field(str) age = Field(int, required=False, default=0)class Product(ORMModel): """Product ORM model.""" title = Field(str) price = Field(float) quantity = Field(int)# ============================================# PART 7: ATTRIBUTE TRACKING AND MODIFICATION# ============================================class AttributeTrackerMeta(type): """ Metaclass that tracks attribute modifications. Useful for change detection and audit trails. """ def __new__(mcs, name, bases, namespace): # Add tracking wrapper to all methods for key, value in namespace.items(): if callable(value) and not key.startswith('_'): namespace[key] = mcs._track_calls(value, key) cls = super().__new__(mcs, name, bases, namespace) # Add tracking list cls._method_calls = [] return cls @staticmethod def _track_calls(method, method_name): """Wrap method to track calls.""" def wrapper(self, *args, **kwargs): call_info = { 'method': method_name, 'args': args, 'kwargs': kwargs, 'timestamp': datetime.now() } self._method_calls.append(call_info) return method(self, *args, **kwargs) return wrapperclass TrackedCalculator(metaclass=AttributeTrackerMeta): """Calculator with method call tracking.""" def add(self, a, b): return a + b def multiply(self, a, b): return a * b def get_history(self): """Get call history.""" return self._method_calls# ============================================# PART 8: ORDERED ATTRIBUTES WITH __prepare__# ============================================class OrderedClassMeta(type): """ Metaclass that preserves attribute definition order. Useful for form fields, schema definitions, etc. """ @classmethod def __prepare__(mcs, name, bases): """Return OrderedDict for namespace.""" return OrderedDict() def __new__(mcs, name, bases, namespace): # namespace is now an OrderedDict cls = super().__new__(mcs, name, bases, dict(namespace)) # Store field order cls._field_order = [ key for key in namespace.keys() if not key.startswith('_') ] return clsclass OrderedForm(metaclass=OrderedClassMeta): """Form with preserved field order.""" username = "string" email = "email" password = "password" age = "integer" country = "select"# ============================================# PART 9: COMBINING MULTIPLE METACLASSES# ============================================class LoggingMeta(type): """Metaclass that adds logging.""" def __new__(mcs, name, bases, namespace): cls = super().__new__(mcs, name, bases, namespace) cls._log = [] return clsclass ValidationMeta(type): """Metaclass that adds validation.""" def __new__(mcs, name, bases, namespace): cls = super().__new__(mcs, name, bases, namespace) cls._validated = True return clsclass CombinedMeta(LoggingMeta, ValidationMeta): """Combined metaclass inheriting from both.""" def __new__(mcs, name, bases, namespace): return super().__new__(mcs, name, bases, namespace)class CombinedClass(metaclass=CombinedMeta): """Class using combined metaclass.""" pass# ============================================# DEMONSTRATION FUNCTIONS# ============================================def demo_basic_metaclass(): """Demonstrate basic metaclass usage.""" print("" + "="*60) print("DEMO: Basic Metaclass") print("="*60) # Class creation triggers __new__ and __init__ obj = DebuggedClass(42) print(f"Created at: {DebuggedClass._created_at}")def demo_singleton(): """Demonstrate singleton pattern.""" print("" + "="*60) print("DEMO: Singleton Pattern") print("="*60) db1 = DatabaseConnection("localhost", 5432) db2 = DatabaseConnection("remote", 3306) # Same instance! print(f"Same instance? {db1 is db2}") print(f"Host: {db1.host}, Port: {db1.port}")def demo_plugin_system(): """Demonstrate plugin registration.""" print("" + "="*60) print("DEMO: Plugin Registration System") print("="*60) print(f"Registered plugins: {len(PluginRegistry.get_plugins())}") for plugin in PluginRegistry.get_plugins(): instance = plugin() print(f" - {plugin.__name__}: {instance.execute()}")def demo_orm(): """Demonstrate ORM functionality.""" print("" + "="*60) print("DEMO: ORM with Field Validation") print("="*60) # Create user user = User(name="Alice", email="alice@example.com", age=30) print(f"User created: {user.to_dict()}") user.save() # Create product product = Product(title="Laptop", price=999.99, quantity=10) print(f"Product created: {product.to_dict()}") product.save() # Validation error example try: invalid_user = User(name="Bob", email=123) # Wrong type except TypeError as e: print(f"❌ Validation error: {e}")def demo_attribute_tracking(): """Demonstrate attribute tracking.""" print("" + "="*60) print("DEMO: Attribute Tracking") print("="*60) calc = TrackedCalculator() result1 = calc.add(5, 3) result2 = calc.multiply(4, 7) result3 = calc.add(10, 20) print(f"Results: {result1}, {result2}, {result3}") print(f"Method call history:") for call in calc.get_history(): print(f" - {call['method']}{call['args']} at {call['timestamp']}")def demo_ordered_attributes(): """Demonstrate ordered attributes.""" print("" + "="*60) print("DEMO: Ordered Attributes") print("="*60) print(f"Field order: {OrderedForm._field_order}") print("Fields in definition order:") for field in OrderedForm._field_order: value = getattr(OrderedForm, field) print(f" - {field}: {value}")# ============================================# MAIN EXECUTION# ============================================if __name__ == "__main__": print("" + "="*60) print("METACLASSES: DEEP DIVE DEMONSTRATION") print("="*60) # Run all demonstrations demonstrate_type_as_factory() demo_basic_metaclass() demo_singleton() demo_plugin_system() demo_orm() demo_attribute_tracking() demo_ordered_attributes() print("" + "="*60) print("✅ All demonstrations completed!") print("="*60)# ============================================# KEY TAKEAWAYS# ============================================"""METACLASS PATTERNS DEMONSTRATED:1. Type as Factory (demonstrate_type_as_factory) - Creating classes dynamically with type() 2. Debug Metaclass (DebugMeta) - Logging class creation, initialization, and instantiation 3. Singleton Pattern (SingletonMeta) - Ensuring only one instance exists 4. Plugin Registry (PluginRegistry) - Automatic registration of subclasses 5. Interface Enforcement (InterfaceEnforcerMeta) - Validating required methods at class creation 6. ORM Pattern (ORMMeta) - Field validation and database abstraction 7. Attribute Tracking (AttributeTrackerMeta) - Monitoring method calls and changes 8. Ordered Attributes (OrderedClassMeta) - Preserving definition order with __prepare__ 9. Multiple Inheritance (CombinedMeta) - Combining multiple metaclassesBEST PRACTICES:- Always call super() in metaclass methods- Use __init_subclass__ for simpler cases (Python 3.6+)- Document metaclass behavior clearly- Provide meaningful error messages- Consider if a decorator would suffice"""