Aangepaste metaklassen schrijven
Gebruik __new__ en __init__ in metaklassen om het maken van klassen aan te passen.
Aangepaste metaklassen schrijven is een gratis Python Academy-les op CoddyKit. Dit is les 2 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Python Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Python Academy bevat in totaal 4 lessen.
Een metaklasse declareren
Geef metaclass=MyMeta op in de klassendefinitie om een aangepaste metaklasse te gebruiken. De metaklasse moet overerven van type.
class MyMeta(type):
pass
class Foo(metaclass=MyMeta):
pass
print(type(Foo)) # <class '__main__.MyMeta'>__new__ overschrijven
__new__(mcs, name, bases, namespace) maakt het klasseobject. Gebruik deze om de naamruimte aan te passen voordat de klasse wordt opgebouwd.
class UpperAttrMeta(type):
def __new__(mcs, name, bases, namespace):
upper = {k.upper(): v for k, v in namespace.items()
if not k.startswith("_")}
return super().__new__(mcs, name, bases, {**namespace, **upper})
class Config(metaclass=UpperAttrMeta):
debug = True
print(Config.DEBUG) # True__init__ overschrijven
__init__(cls, name, bases, namespace) wordt uitgevoerd nadat de klasse is aangemaakt. Gebruik deze voor instellingen na het aanmaken, zoals registratie.
_registry = {}
class AutoRegisterMeta(type):
def __init__(cls, name, bases, namespace):
super().__init__(name, bases, namespace)
if bases: # skip the base class itself
_registry[name] = cls
class Handler(metaclass=AutoRegisterMeta): pass
class JSONHandler(Handler): pass
class XMLHandler(Handler): pass
print(_registry) # {'JSONHandler': ..., 'XMLHandler': ...}Interfacecontracten afdwingen
Gooi TypeError op in __new__ als vereiste methoden ontbreken in de klassebody.
class InterfaceMeta(type):
REQUIRED = frozenset({"process", "validate"})
def __new__(mcs, name, bases, ns):
if bases and not mcs.REQUIRED.issubset(ns):
missing = mcs.REQUIRED - ns.keys()
raise TypeError(f"{name} must define: {missing}")
return super().__new__(mcs, name, bases, ns)
class Worker(metaclass=InterfaceMeta):
def process(self): ...
def validate(self): ...Singleton via een metaklasse
Overschrijf __call__ op de metaklasse om het aanmaken van instanties te onderscheppen en elke keer dezelfde instantie te retourneren.
class SingletonMeta(type):
_instances = {}
def __call__(cls, *a, **kw):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*a, **kw)
return cls._instances[cls]
class DB(metaclass=SingletonMeta):
pass
print(DB() is DB()) # TrueDynamisch methoden toevoegen
Voeg hulmethoden in elke klasse in die de metaklasse gebruikt, zonder elke klasse afzonderlijk aan te passen.
class MethodInjectorMeta(type):
def __new__(mcs, name, bases, ns):
ns["describe"] = lambda self: f"I am {type(self).__name__}"
return super().__new__(mcs, name, bases, ns)
class Widget(metaclass=MethodInjectorMeta):
pass
print(Widget().describe()) # I am Widget__prepare__ voor een geordende naamruimte
Overschrijf __prepare__ om een aangepaste toewijzing als klassenaamruimte aan te leveren, bijvoorbeeld om de volgorde van definities te behouden of duplicaten te detecteren.
class NoDuplicatesMeta(type):
class _NS(dict):
def __setitem__(self, k, v):
if k in self and not k.startswith("_"):
raise ValueError(f"Duplicate attribute: {k}")
super().__setitem__(k, v)
@classmethod
def __prepare__(mcs, name, bases):
return mcs._NS()Conflicten tussen metaklassen oplossen
Wanneer meerdere basisklassen verschillende metaklassen hebben, vereist Python dat de meest specifieke metaklasse expliciet wordt gebruikt; anders wordt een conflictfout opgegooid.
class MetaA(type): pass
class MetaB(type): pass
# class Bad(A, B): pass # TypeError: metaclass conflict
class MetaAB(MetaA, MetaB): pass # resolve manually
class A(metaclass=MetaA): pass
class B(metaclass=MetaB): pass
class Good(A, B, metaclass=MetaAB): passMetaklasse versus __init_subclass__
Voor registratie van subklassen en eenvoudige haken is __init_subclass__ eenvoudiger en is geen metaklasse nodig.
class Base:
_registry = []
def __init_subclass__(cls, **kw):
super().__init_subclass__(**kw)
Base._registry.append(cls)
class ChildA(Base): pass
class ChildB(Base): pass
print(Base._registry) # [ChildA, ChildB]Toegang tot attributen traceren
Overschrijf __getattribute__ op de metaklasse om toegang tot attributen op de klasse te onderscheppen (niet op instanties).
class TraceMeta(type):
def __getattribute__(cls, name):
val = super().__getattribute__(name)
if not name.startswith("_"):
print(f"Accessing class attr: {name}")
return val
class Config(metaclass=TraceMeta):
HOST = "localhost"
_ = Config.HOST # logs: Accessing class attr: HOSTPatroon voor het verzamelen van ORM-velden
ORM's in Django-stijl gebruiken metaklassen om Field-descriptors uit de klassebody te verzamelen in een _meta-register.
class Field:
def __init__(self, col): self.col = col
class ModelMeta(type):
def __new__(mcs, name, bases, ns):
fields = {k: v for k, v in ns.items() if isinstance(v, Field)}
ns["_fields"] = fields
return super().__new__(mcs, name, bases, ns)
class User(metaclass=ModelMeta):
name = Field("name")
email = Field("email")
print(User._fields.keys()) # dict_keys(['name', 'email'])Korte controle
Welke methode wordt in een aangepaste metaklasse aangeroepen om het klasseobject zelf te maken (vóór __init__)?
Samenvatting
Aangepaste metaklassen overschrijven __new__/__init__ om het aanmaken van klassen te sturen: contracten afdwingen, subklassen automatisch registreren, methoden invoegen of veld-descriptors verzamelen. Geef voor eenvoudige registratiebehoeften de voorkeur aan __init_subclass__.
Leer Python met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 76
- Lessen
- 320
Veelgestelde vragen
Is de les “Aangepaste metaklassen schrijven” gratis?
Ja — de volledige tekst van “Aangepaste metaklassen schrijven” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Python Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Python Academy bevat in totaal 4 lessen.
Wat leer ik in “Aangepaste metaklassen schrijven”?
Gebruik __new__ en __init__ in metaklassen om het maken van klassen aan te passen. Je oefent met Python Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Python Academy te beginnen?
Ervaring vooraf is niet nodig. Python Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 2 van 4.
Hoe lang duurt de les “Aangepaste metaklassen schrijven”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Python Academy?
Ja. Elke les over Python Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Hoe Python-klassen worden gemaakt
- Aangepaste metaklassen schrijven
- Descriptors: __get__, __set__, __delete__
- __slots__ en geheugenoptimalisatie