Metaklassen in Python — sind spezielle Klassen, die andere Klassen erstellen und verwalten. Da in Python alles ein Objekt ist, einschließlich Klassen, können Metaklassen als "Klassen für Klassen" betrachtet werden. Sie bieten einen Mechanismus zur Kontrolle des Erstellungsprozesses von Klassen und zur Änderung ihres Verhaltens zum Zeitpunkt der Definition.
Funktionsweise von Metaklassen
Wenn Python auf eine Klassendefinition trifft, verwendet es automatisch die Metaklasse type, um diese Klasse zu erstellen. Der Prozess sieht wie folgt aus:
class MyClass:
pass
Intern führt Python Folgendes aus:
MyClass = type('MyClass', (), {})
Wobei:
'MyClass'— der Name der Klasse()— das Tupel der Elternklassen{}— das Wörterbuch der Attribute und Methoden der Klasse
Die eingebaute Metaklasse type ist standardmäßig für die Erstellung aller Klassen in Python verantwortlich.
Eigene Metaklassen erstellen
Benutzerdefinierte Metaklassen werden durch Vererbung von type und Überschreiben seiner Methoden erstellt:
class MyMeta(type):
def __new__(cls, name, bases, attrs):
print(f"Erstelle Klasse {name}")
attrs['created_by_metaclass'] = True
return super().__new__(cls, name, bases, attrs)
class MyClass(metaclass=MyMeta):
pass
print(MyClass.created_by_metaclass) # True
Wichtige Methoden von Metaklassen
__new__
Steuert die Erstellung der Klasse. Wird vor __init__ aufgerufen und gibt die neue Klasse zurück:
class CreationMeta(type):
def __new__(cls, name, bases, attrs):
# Attribute vor der Klassenerstellung modifizieren
attrs['class_id'] = id(cls)
return super().__new__(cls, name, bases, attrs)
__init__
Initialisiert die bereits erstellte Klasse:
class InitMeta(type):
def __init__(cls, name, bases, attrs):
print(f"Initialisiere Klasse {name}")
super().__init__(name, bases, attrs)
__call__
Definiert das Verhalten beim Erstellen von Instanzen der Klasse:
class CallMeta(type):
def __call__(cls, *args, **kwargs):
print(f"Erstelle Instanz von {cls.__name__}")
return super().__call__(*args, **kwargs)
Praktische Anwendungsbeispiele
Automatische Attribut-Transformation
class UpperAttrMeta(type):
def __new__(cls, name, bases, attrs):
uppercase_attrs = {}
for attr_name, attr_value in attrs.items():
if not attr_name.startswith('__'):
uppercase_attrs[attr_name.upper()] = attr_value
else:
uppercase_attrs[attr_name] = attr_value
return super().__new__(cls, name, bases, uppercase_attrs)
class MyClass(metaclass=UpperAttrMeta):
attr1 = 'value1'
attr2 = 'value2'
print(hasattr(MyClass, 'ATTR1')) # True
print(hasattr(MyClass, 'attr1')) # False
Singleton-Pattern implementieren
class SingletonMeta(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class DatabaseConnection(metaclass=SingletonMeta):
def __init__(self):
print("Erstelle Datenbankverbindung")
db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(db1 is db2) # True
Validierung der Klassenstruktur
class ValidatedMeta(type):
def __new__(cls, na