Zur Laufzeit Klassen erstellen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
DKKA
User
Beiträge: 45
Registriert: Freitag 18. Oktober 2013, 14:20

Hallo,

Ich suche Links/Literatur darüber, wie ich dynamisch während der Laufzeit Klassen erstellen und Methoden hinzufügen kann oder wieder wegnehmen kann. Vielleicht mit ein paar Beispielen. Könnt ihr mir weiterhelfen? Und was genau ist da alles möglich in Python, Python ist doch recht dynamisch und erzeugt die Klassen intern doch immer erst zur Laufzeit? Und ist es möglich, ohne

Code: Alles auswählen

class A(object):
Eine Klasse zu erstellen? So was wie ne "anonyme" Klasse?


Vielen Dank!
BlackJack

@DKKA: Dynamisch zur Laufzeit eine Klasse zu erstellen geht ganz einfach mit der ``class``-Anweisung. Jede Klasse wird in Python nämlich dynamisch zur Laufzeit erstellt. Der *Klasse* Methoden hinzuzufügen oder wegzunehmen geht genau so wie mit jedem anderen Objekt. Klassen sind Objekte und die haben Attribute.

Wobei man so etwas praktisch besser nicht machen sollte, ausser in Ausnahmefällen (Stichwort „monkey patching”).

Wozu brauchst Du eine anonyme Klasse? Was stört Dich daran, dass eine Klasse einen Namen hat? Du kannst mit ``class`` auch problemlos verschiedene Klassen mit dem gleichen Namen erzeugen. Jedes mal wenn die ``class``-Anweisung ausgeführt wird, dann wird eine *neues* Klassenobjekt erstellt. Ansonsten geht das mit der `type()`-Funktion wenn man ``class`` unbedingt vermeiden will. Das erste Argument muss aber auch dort der Name des zu erzeugenden Datentyps, also der Klasse, sein.
DKKA
User
Beiträge: 45
Registriert: Freitag 18. Oktober 2013, 14:20

BlackJack hat geschrieben:@DKKA: Dynamisch zur Laufzeit eine Klasse zu erstellen geht ganz einfach mit der ``class``-Anweisung. Jede Klasse wird in Python nämlich dynamisch zur Laufzeit erstellt. Der *Klasse* Methoden hinzuzufügen oder wegzunehmen geht genau so wie mit jedem anderen Objekt. Klassen sind Objekte und die haben Attribute.

Wobei man so etwas praktisch besser nicht machen sollte, ausser in Ausnahmefällen (Stichwort „monkey patching”).

Wozu brauchst Du eine anonyme Klasse? Was stört Dich daran, dass eine Klasse einen Namen hat? Du kannst mit ``class`` auch problemlos verschiedene Klassen mit dem gleichen Namen erzeugen. Jedes mal wenn die ``class``-Anweisung ausgeführt wird, dann wird eine *neues* Klassenobjekt erstellt. Ansonsten geht das mit der `type()`-Funktion wenn man ``class`` unbedingt vermeiden will. Das erste Argument muss aber auch dort der Name des zu erzeugenden Datentyps, also der Klasse, sein.
Heisst das, ich kann bestehende überschreiben a la:

Code: Alles auswählen

Some_class.old_method = new_method
und wie kann ich direkt neue hinzufügen?

Genau das mit Type interessiert mich. So eine Art Metaklasse, nur verstehe ich das Konzept dahinter nicht wirklich. Wie funktioniert das genau? ich übergebe der type-funktion den Namen der neuen Klasse+Methoden+Attribute? Kann ich nachher von dieser Klasse vererben lassen? Sorry, versteh das nicht so ganz.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

DKKA hat geschrieben:Heisst das, ich kann bestehende überschreiben a la:

Code: Alles auswählen

Some_class.old_method = new_method
Ja. Das kannst du auch ganz leicht selber ausprobieren ;-)
DKKA hat geschrieben:und wie kann ich direkt neue hinzufügen?
Hat BlackJack schon geschrieben. Klassen sind ganz normale Objekte, den kannst du einfach ein weiteres Attributt hinzufügen. Und wenn das Attribut eine Funktion ist, dann hast du eine neue Methode.
DKKA hat geschrieben:Genau das mit Type interessiert mich. So eine Art Metaklasse, nur verstehe ich das Konzept dahinter nicht wirklich. Wie funktioniert das genau? ich übergebe der type-funktion den Namen der neuen Klasse+Methoden+Attribute? Kann ich nachher von dieser Klasse vererben lassen? Sorry, versteh das nicht so ganz.
Am besten schaust du dir dazu die Dokumentation zu type an und probierst einfach aus.
Das Leben ist wie ein Tennisball.
BlackJack

@DKKA: Neue fügst Du hinzu wie Du alte überschreibst. Wenn das Attribut `old_method` vorher nicht existierte, tut es das nach der Zuweisung ja.

Zu `type()` schau Dir doch einfach die Dokumentation an. Das erste Argument ist der Name, das zweite ein Tupel mit den Basisklassen, und das dritte ein Wörterbuch mit den Attributen. Und ja von dem Ergebnis kann man dann natürlich auch erben, sonst wäre es ja keine Klasse.
Benutzeravatar
/me
User
Beiträge: 3556
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

DKKA hat geschrieben: Heisst das, ich kann bestehende überschreiben a la:

Code: Alles auswählen

Some_class.old_method = new_method
und wie kann ich direkt neue hinzufügen?
Das ist keine Hexerei.

Code: Alles auswählen

>>> class Foo():
    def bar(self, x):
        return x * x

>>> def baz(self, x):
    return x / 2

>>> thing = Foo()
>>> print(thing.bar(3))
9
>>> Foo.bar = baz
>>> print(thing.bar(3))
1.5
>>> Foo.newbar = baz
>>> print(thing.newbar(3))
1.5
Malachite
User
Beiträge: 34
Registriert: Sonntag 24. Juni 2012, 13:43
Wohnort: Berlin

Man kann tatsächlich "anonyme" Klassen in Python erstellen, da Klassen in Python, wie alles andere auch, Objekte sind. Diese Objekte können haben zufällig die Eigenschaft, selbst Objekte zu erstellen, wenn man sie aufruft, deshalb nennt man sie Klassen.

Die Klasse einer Klasse wird Metaklasse genannt. Jede Klasse hat eine Metaklasse, entweder type oder eine Klasse, die von type erbt. Die Klasse type ist ihre eigene Metaklasse.

Da jede Klasse also eine Instanz einer Metaklasse ist, kann man über den Konstruktor der Metaklasse theoretisch dynamisch Klassen erstellen. Wie gesagt, theoretisch. Zum Experimentieren ist das ganz nett, aber wenn du es vermeiden kannst, solche Klassen in Produktionscode zu erstellen, dann vermeide es.

Die Syntax ist folgendermaßen:

Code: Alles auswählen

type(name: str,  # Der Name der Klasse. Wird zum Attribut __name__.
bases: tuple,  # Die Klassen, von denen die Klasse erbt. Wird zum Attribut __bases__.
attributes: dict  # Die Attribute der Klasse. Wird zum Attribut __dict__.
)
Beispiel:

Code: Alles auswählen

>>> type('Printer', (object,), {'__init__': print})("Hello World!")
Hello World!
<__main__.Printer object at 0xabcdefabcdef>

# Äquivalent zu:
class Printer():
    __init__ = print  # def __init__… geht nicht in einer anonymen Klasse
Da man meines Wissens keine nicht-Lambda-Funktionen dynamisch erstellen kann, müssen die Methoden der Klasse entweder bereits definiert oder Lambda-Funktionen sein.

Auf Stack Overflow gibt es einen englischen, noch ausführlicheren Post zum Thema Metaklassen: http://stackoverflow.com/questions/1000 ... -in-python
BlackJack

@Malachite: Man kann nicht nur „normale” Funktionen dynamisch erstellen sondern *jede* Funktion die man erstellt, wird dynamisch erstellt.
DKKA
User
Beiträge: 45
Registriert: Freitag 18. Oktober 2013, 14:20

Mit der Type-Funktion kann ich ja die Attribute mittels eines Dictionarys übergeben. Gibt es auch eine Möglichkeit, wie ich das nach erzeugen eines Objektes machen kann? So dass ich einfach nur ein Dict. übergeben kann ohne alle Attribute einzeln zu überschreiben mit self.x = x....?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Suchst du eventuell… Schleifen? (Gut, theoretisch kannst du auch ``deineklasse.__dict__.update`` nutzen, aber das würde ich persönlich meiden).
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

@DKKA: Ich schliesse mich Leonidas an und werfe noch `setattr()` in den Topf.
DKKA
User
Beiträge: 45
Registriert: Freitag 18. Oktober 2013, 14:20

BlackJack hat geschrieben:@DKKA: Ich schliesse mich Leonidas an und werfe noch `setattr()` in den Topf.
setattr() hab ich gesucht!! vielen dank!
Antworten