Advanced Metaclasses
Metaclass basics, new, init_subclass, and metaclass patterns.
Overview
Master metaclass concepts.
Metaclass Basics
class Meta(type):
def __new__(cls, name, bases, attrs):
# Add prefix to all methods
for key, value in attrs.items():
if callable(value) and not key.startswith('_'):
attrs[f'custom_{key}'] = value
return super().__new__(cls, name, bases, attrs)
class MyClass(metaclass=Meta):
def method(self):
return "original"
obj = MyClass()
print(obj.custom_method()) # original
init_subclass
class Plugin:
plugins = []
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
Plugin.plugins.append(cls)
class PluginA(Plugin):
pass
class PluginB(Plugin):
pass
print(Plugin.plugins) # [<class 'PluginA'>, <class 'PluginB'>]
Validation Metaclass
class ValidatedMeta(type):
def __new__(cls, name, bases, attrs):
for key, value in attrs.items():
if isinstance(value, str) and not key.startswith('_'):
attrs[key] = property(
lambda self, v=value: getattr(self, f'_{v}', None),
lambda self, v, key=key: setattr(self, f'_{key}', v)
)
return super().__new__(cls, name, bases, attrs)
class User(metaclass=ValidatedMeta):
name = "str"
email = "str"
u = User()
u.name = "Alice"
print(u.name) # Alice
Practice
Create a metaclass that automatically adds logging to all methods.