Seite 1 von 1

Zur Laufzeit Klassen erstellen

Verfasst: Mittwoch 4. Dezember 2013, 12:49
von DKKA
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!

Re: Zur Laufzeit Klassen erstellen

Verfasst: Mittwoch 4. Dezember 2013, 13:00
von 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.

Re: Zur Laufzeit Klassen erstellen

Verfasst: Mittwoch 4. Dezember 2013, 13:16
von DKKA
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.

Re: Zur Laufzeit Klassen erstellen

Verfasst: Mittwoch 4. Dezember 2013, 13:47
von EyDu
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.

Re: Zur Laufzeit Klassen erstellen

Verfasst: Mittwoch 4. Dezember 2013, 13:48
von 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.

Re: Zur Laufzeit Klassen erstellen

Verfasst: Mittwoch 4. Dezember 2013, 13:55
von /me
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

Re: Zur Laufzeit Klassen erstellen

Verfasst: Mittwoch 11. Dezember 2013, 21:29
von Malachite
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

Re: Zur Laufzeit Klassen erstellen

Verfasst: Mittwoch 11. Dezember 2013, 22:22
von BlackJack
@Malachite: Man kann nicht nur „normale” Funktionen dynamisch erstellen sondern *jede* Funktion die man erstellt, wird dynamisch erstellt.

Re: Zur Laufzeit Klassen erstellen

Verfasst: Donnerstag 12. Dezember 2013, 23:27
von DKKA
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....?

Re: Zur Laufzeit Klassen erstellen

Verfasst: Freitag 13. Dezember 2013, 00:32
von Leonidas
Suchst du eventuell… Schleifen? (Gut, theoretisch kannst du auch ``deineklasse.__dict__.update`` nutzen, aber das würde ich persönlich meiden).

Re: Zur Laufzeit Klassen erstellen

Verfasst: Freitag 13. Dezember 2013, 00:42
von BlackJack
@DKKA: Ich schliesse mich Leonidas an und werfe noch `setattr()` in den Topf.

Re: Zur Laufzeit Klassen erstellen

Verfasst: Freitag 13. Dezember 2013, 00:54
von DKKA
BlackJack hat geschrieben:@DKKA: Ich schliesse mich Leonidas an und werfe noch `setattr()` in den Topf.
setattr() hab ich gesucht!! vielen dank!