Methoden zur Laufzeit erzeugen

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
ignis-draco
User
Beiträge: 15
Registriert: Freitag 25. Februar 2011, 12:33

Hi


ich habe eine Frage. Gibt es eine Möglichkeit einer Klasse (oder Instanz) neue Methoden zu geben ?

Mir geht es da rum. Ich habe eine XML Datei in der Namen stehen. Aus diesen Namen würde ich gerne Getter und Setter Methoden generieren.
Mittel exec könnte ich dann den generierten String ausführen jedoch müsste ich dann bei der Instanz den Aufruf der Methode umlenken.
Idee war das ich eine dic von Name und String habe und beim Aufruf der Methode sie dann mittel exec ausführe.
Schöner wäre es aber wenn ich bei der Class schon in dem __dict__ die Methoden anlegen könnte und zwar so das wenn ich eine Instanz erzeuge die Methoden
von Außerhalb erreichbar sind. Gibt es da einen Weg? Habe in der Doku leider nichts Passendes gefunden.

Ach bevor ich es vergesse ich benutze Python 3.

Danke schon mal im voraus
Gruß
Ignis-draco
lunar

@ignis-draco: Du kannst einer Klasse Funktionen als Attribute zuweisen, die sich dann von außen im Wesentlichen nicht von Methoden unterscheiden:

Code: Alles auswählen

>>> class Spam:
...     def __init__(self, no_eggs):
...         self.no_eggs = no_eggs
...     def real_method(self):
...         print('calling the real method with {0} eggs'.format(self.no_eggs))
... 
>>> spam = Spam(10)
>>> spam.real_method()
calling the real method with 10 eggs
>>> def fake_method(self):
...     print('calling the fake method with {0} eggs'.format(self.no_eggs))
... 
>>> from functools import partial
>>> spam.fake_method = partial(fake_method, spam)
>>> spam.fake_method()
calling the fake method with 10 eggs
Ich rate Dir allerdings davon ab, Exemplare zur Laufzeit von außen um Attribute zu erweitern. Das ist zwar bequem, der Verständlichkeit des Quelltexts allerdings abträglich, da man die in einem Exemplar einer Klasse existierende Attribute dann nicht mehr allein aus der Definition der Klasse ablesen kann, sondern den ganzen Quelltext des Projekts absuchen muss.

Ich glaube auch nicht, dass dieser Weg wirklich die beste Lösung für das Problem ist, welches Du eigentlich lösen möchtest. Die Verwendung der Begriffe „Getter“ und „Setter“ im Zusammenhang mit Methoden lassen mich vermuten, dass Du die üblichen Idiome in Python auch noch nicht vollständig beherrscht, denn explizite Getter- und Setter-Methoden verwendet man in Python nicht.
ignis-draco
User
Beiträge: 15
Registriert: Freitag 25. Februar 2011, 12:33

lunar hat geschrieben:@ignis-draco: Du kannst einer Klasse Funktionen als Attribute zuweisen, die sich dann von außen im Wesentlichen nicht von Methoden unterscheiden:

Code: Alles auswählen

>>> class Spam:
...     def __init__(self, no_eggs):
...         self.no_eggs = no_eggs
...     def real_method(self):
...         print('calling the real method with {0} eggs'.format(self.no_eggs))
... 
>>> spam = Spam(10)
>>> spam.real_method()
calling the real method with 10 eggs
>>> def fake_method(self):
...     print('calling the fake method with {0} eggs'.format(self.no_eggs))
... 
>>> from functools import partial
>>> spam.fake_method = partial(fake_method, spam)
>>> spam.fake_method()
calling the fake method with 10 eggs
cool danke. Das hilft mir viel weiter.
lunar hat geschrieben: Ich rate Dir allerdings davon ab, Exemplare zur Laufzeit von außen um Attribute zu erweitern. Das ist zwar bequem, der Verständlichkeit des Quelltexts allerdings abträglich, da man die in einem Exemplar einer Klasse existierende Attribute dann nicht mehr allein aus der Definition der Klasse ablesen kann, sondern den ganzen Quelltext des Projekts absuchen muss.
Da stimmt ich dir im Normal Fall zu. Jedoch geht es in diesem Projekt darum Daten die über ein TCP Protokoll rein kommen einem anderem Teil des Programms zur Verfügung zustellen. Und da
das Protokoll nun mal über die XML Dateien Spezifiziert wird sind die (was die Kommunikation angeht) die Zentrale stellen. Zu dem möchte mein Vorgesetzter das so.
lunar hat geschrieben: Ich glaube auch nicht, dass dieser Weg wirklich die beste Lösung für das Problem ist, welches Du eigentlich lösen möchtest. Die Verwendung der Begriffe „Getter“ und „Setter“ im Zusammenhang mit Methoden lassen mich vermuten, dass Du die üblichen Idiome in Python auch noch nicht vollständig beherrscht, denn explizite Getter- und Setter-Methoden verwendet man in Python nicht.
Das weiß ich. Jedoch passiert bei mit in den gettern und Settern noch etwas mehr als nur Zuweisung einer Variabel.
Ich hatte auch erst überlegt das ganze durch "@property" zu machen aber bei den Gettern soll mit angegeben werden können wie Aktuell die Daten seinen sollen damit nur dann neue Daten angefordert werden
wenn sie benötigt wird (mittel TCP).

Dein beispiel Hilft mir sehr. Werde das Morgen gleich mal ausprobieren.
Gruß
ignis-draco
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ich werfe dann mal den Begriff Metaklassen in den Raum ...
Das Leben ist wie ein Tennisball.
BlackJack

@ignis-draco: Ich würde noch mal beim ``exec`` und den generierten Zeichenketten dafür einhaken: Quelltext generieren muss man normalerweise bei statischen Sprachen wenn man an die Grenzen der Sprache stösst. In Python gibt es nur sehr selten die notwendigkeit auf dieses Mittel zurück zu greifen.

Wie wird denn auf die dynamisch erzeugten Methoden dann zugegriffen? Der Programmierer muss dann ja wissen welche Methoden es gibt, damit er die Aufrufe in den Quelltext schreiben kann.
ignis-draco
User
Beiträge: 15
Registriert: Freitag 25. Februar 2011, 12:33

BlackJack hat geschrieben: Wie wird denn auf die dynamisch erzeugten Methoden dann zugegriffen? Der Programmierer muss dann ja wissen welche Methoden es gibt, damit er die Aufrufe in den Quelltext schreiben kann.
Für den Programmierer soll es kein unterscheid geben ob er eine "normale" Methode oder auf einen nachträglich geladene Methode benutz.
Die Benennung kann er der xml Datei entnehmen. Vielleicht ist auch "zur Laufzeit" eine falsche Beschreibung.
Die Methoden werden halt einmal zu beginn geladen/erzeugt und danach nur noch benutzt.


Gruß
Ignis-draco
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Hallo ignis-draco,

Ich bin nicht 100% sicher ob ich den Vorhaben komplett verstanden habe. Mein Annahme: Du hast ein XML Konstrukt als Input und du möchtest die Modifikation der Attribute in diesem Baum kapseln und als API zur Verfügung stellen.

Wenn ja, würde würde ich versuchen, auf zur Laufzeit erzeugte getter und setter zu verzichten, und statt dessen einfach generische Methoden wie z.B. set() und get() etc. bereit zu stellen.
Hier könntest du einfach API und Verhalten beschreiben und der Programmierer muss auch nichts anderes tun als Attributänderungen wie folgt durchführen:

Code: Alles auswählen

obj.set("foo", new_value, ...) 
Wie BlackJack schon sagte, der Entwickler muss ja irgendwo her die Namen der getter und setter Methoden wissen.
Angenommen du entwickelst aufwändig deine getter und setter Generierung, welche im Quellcode der Endanwender bestimmt schick aussehen. Aber nun kommt ein Entwickler und möchte alle Attribute eines XML Knotens einfach mal ausgeben. Und das dynamisch, ohne die getter und setter zu kennen und von Hand zu tippen.

Dies wäre mit der einfachen Herangehensweise möglich:

Code: Alles auswählen

for attribname in obj.attribnames:
    print(obj.get(attribname)
.. mit dem getter und setter Ansatz aber wieder umständlich.
deets

Ich halte das fuer einen falschen Ansatz. Mir ist vor allem auch noch nicht klar, was *Methoden* da sollen - wenn's sowieso nur simple getter/setter sind, dann nimm halt gleich Attribute. Oder sollen diese Methoden etwas mehr koenne? Wenn ja - was, und woher wissen sie's?

Ich denke ein einfacher "Bunch" reicht da aus. Dann kann man auf die Attribute eines Objektes etwas "schoener" zugreifen:

Code: Alles auswählen


class Bunch(object):
     def __init__(self, **kwargs):
           self.__dict__.update(kwargs)

a = Bunch(dict(foo="bar"))
print a.foo
ignis-draco
User
Beiträge: 15
Registriert: Freitag 25. Februar 2011, 12:33

Hi


Ich versuche mal mich etwas genauer auszudrücken.

Bei der get-Methode wird überprüft ob die Aktualität des Wertes noch ok ist, wenn ja werden die Lokalen Daten zurückgegeben wenn nicht wird eine anfrage an die Kommunikations
Instanz gesendet und ein Semaphor versucht zu bekommen. Der Semaphor wird benötigt da die Kommunikation als eigener thread abläuft.
Also einfach auf die Atribute zugreifen geht so nicht.

In den xml Dateien steht nur welches Objekt welche Atribute hat und ob man sie setzen und/oder nur auslesen kann.
Das mit den Namen habt ihr Recht. Das war auch die anmerke die ich hatte. Aber auf der anderen Seite ist es ja egal ob ich in der klasse nachschaue wie die Methode heißt oder ob ich gerade in die xml Datei schaue.

Zu der Sache mit der Ausgabe. Das ist kein Problem man muss sich nur das dict ausgeben lassen dann hat man alles. Ich habe für die werte Lokal ein dict mit {NAME:(Aktualität, Daten, Semaphor)}.
Da stehen alles werte drin.

Ich hoffe es ist jetzt klarer geworden. Werde jetzt mal das von lunar ausprobieren. Melde mich wenn es geklappt hat.

Gruß
Ignis-draco
Antworten