Klassenmethoden zur Laufzeit definieren

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.
hiasl
User
Beiträge: 31
Registriert: Donnerstag 20. April 2006, 13:36

Klassenmethoden zur Laufzeit definieren

Beitragvon hiasl » Freitag 16. März 2007, 10:18

Hallo,

ich würde gerne soetwas wie unten programmieren, geht aber nicht. Das einzige, was ich geschaft habe ist, Funktionen im Konstruktor zu definieren und danach einem Klassenattribut zuzuweisen. Dann allerdings muss ich der Methode das Objekt selbst explizit übergeben: x.t(x). Das ist natürlich nicht schön.

Code: Alles auswählen

class X(object):
   __metaclass__ = meta
   x = 0

   if x:
      def t(self):
         print "A"
   else:
      def t(self):
         print "B"

x = X(0)
x.t() # => "B"
x = X(1)
x.t() => "A"


Falls jemand einen Tipp hat wäre ich dankbar.

Gruß
Matthias
EyDu
User
Beiträge: 4866
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Beitragvon EyDu » Freitag 16. März 2007, 10:25

Vielleicht liegt es nur an dem einfachen Beispiel, aber für so etwas verwendet man normalerweise Vererbung.
hiasl
User
Beiträge: 31
Registriert: Donnerstag 20. April 2006, 13:36

Beitragvon hiasl » Freitag 16. März 2007, 10:33

Es liegt am einfachen Beispiel ;)
BlackJack

Beitragvon BlackJack » Freitag 16. März 2007, 10:41

Oder in diesem Beispiel alternativ eine Factory-Funktion die eines von zwei Objekten zurückgibt.

Oder man übergibt 'A' oder 'B' im Konstruktor und gibt dass dann entsprechend aus.


Da das Beispiel aber viel zu einfach ist, kann man das nicht sagen. Welches Problem soll denn gelöst werden? Und bitte das Problem nicht in Form einer Lösung beschreiben, sondern wirklich das *Problem* selbst.
hiasl
User
Beiträge: 31
Registriert: Donnerstag 20. April 2006, 13:36

Beitragvon hiasl » Freitag 16. März 2007, 11:03

Ich will unterschiedliche Dinge in einer Klasse kapseln, unter möglichst hoher Wahrung von Transparenz. Das bedeutet, dass mit "isinstance", "instanceof" & co. keine Unterscheidung möglich sein soll.

Aus diesen Gründen scheiden Vererbung und Factories aus.

Deshalb zurück zur problembeschreibenden Fragestellung:
Kann man "Klassenmethoden zur Laufzeit definieren"?

Was ich bisher hinbekommen habe ist:

Code: Alles auswählen

class X(object):
    define __init__(self, x):
        if x:
            def t(self):
                print "A"
        else:
            def t(self):
                print "B"
       self.t = t

y = X(1)
y.t(y) #=> A
y = X(0)
y.t(y) #=> B


Wie man sieht, muss dann aber das Objekt als Instanz übergeben werden.
Vielleicht kann man ja eine Funktion als Objektfunktion registrieren?
BlackJack

Beitragvon BlackJack » Freitag 16. März 2007, 11:18

Du versuchst da etwas zu machen was unpythonisch ist -- Stichwort "duck typing". Der Typ sollte egal sein, wichtig ist das Verhalten des Objekts.
hiasl
User
Beiträge: 31
Registriert: Donnerstag 20. April 2006, 13:36

Beitragvon hiasl » Freitag 16. März 2007, 11:38

Was meine Frage leider nicht beantwortet.

Im übrigen ist eine solche Implementierung selbstverständlich pythonic. Denn meine Klasse sieht nicht nur aus wie eine Ente, quackt wie eine Ente, sondern da steht sogar noch "Ente" drauf".
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Beitragvon Zap » Freitag 16. März 2007, 11:56

sondern da steht sogar noch "Ente" drauf".


das macht es ja eben unpythonic.
duck-typing ist wenn Hund drauf stehen würde und der sich wie die Ente verhält ;)

Ich weiß, das hilft bei deinem Problem nicht weiter, aber oft ist es besser nochmal drüber nachzudenken wie wichtig das mit dem gleichen "aussehen" deiner instanzen ist
hiasl
User
Beiträge: 31
Registriert: Donnerstag 20. April 2006, 13:36

Beitragvon hiasl » Freitag 16. März 2007, 12:20

Mir ist klar, was "Duck typing" ausmacht. Deshalb nochmal:

Meine Klasse ist konform zu dem Paradigma, da die Menge aller Objekte, die sich wie Enten verhalten, eine Obermenge der Objekte ist, die sich wie Enten verhalten und bei denen zusätzlich "Ente" draufsteht.
=> Wenn man auf der Obermenge pythonic arbeiten kann, kann man das folglich auch mit der Untermenge. Das Ganze verursacht erst Probleme wenn man auf der Obermenge operiert und ein Kriterium der Untermenge nutzt - das ist der vorher angesprochene Kontext.

Im übrigen bleibt es jedem selbst überlassen, ob er pythonic programmiert oder nicht. Ich brauche das zum Beisipiel, um Geräte wie Achsen, Roboter, etc. über .dlls, .so oder sockets einzubinden. Denen kann ich noch so oft sagen, "quacke" wie eine Ente. Sie tuns nicht ;). Was an dieser Stelle erreicht werden soll, ist eine absolute Trennung zwischen einer Steuerungsarchitektur und den angeschlossenen Geräten. Und dazu gehört auch, dass ein Anwendungsprogrammierer "unpythonic" programmieren könnte. Ich kann diesen Fall nicht ausschließen und auch nicht jeden Programmierer zu einem Kurs in "duck typing" schicken.

Jedes Paradigma stößt an Grenzen, wenn mit anderen Systemen interagiert werden muss.
Benutzeravatar
Dill
User
Beiträge: 470
Registriert: Mittwoch 10. Januar 2007, 14:52
Wohnort: Köln

Beitragvon Dill » Freitag 16. März 2007, 12:22

BlackJack

Beitragvon BlackJack » Freitag 16. März 2007, 12:43

Na dann korrigiere ich erstmal Deine Frage: "Ist es möglich Instanzmethoden zu einem Objekt hinzuzufügen?", denn an die Klasse möchtest Du die ja nicht binden.

Die Antwort ist: "Ja." :twisted:

Und zu Deinem Problem dass Du beschreibst: Das hört sich nach einem Fall für Komposition an.

Das mit den Unter- und Obermengen ist nett, aber das unpythonische ist die Verwendung von `isinstance()`. Das muss ja wohl irgendwo verwendet werden um diesen ganz bestimmten Typ zu testen, ansonsten gäb's das Problem nicht und man könnte auch den quakenden Hund benutzen.

Wieso kann man den Programmierern nicht die idiomatische Verwendung einer Programmiersprache beibringen? Wenn Du eine Sprache willst, in der man sich nur sehr schwer in den Fuss schiessen kann, bist Du bei Python falsch und solltest lieber eine "discipline & bondage"-Sprache wie Java verwenden. Von einem Python-Programmierer wird im allgemeinen erwartet, dass er weiss was er da tut. Das ist der Preis den man für die Flexibilität und Dynamik zahlen muss.
hiasl
User
Beiträge: 31
Registriert: Donnerstag 20. April 2006, 13:36

Beitragvon hiasl » Freitag 16. März 2007, 13:08

BlackJack hat geschrieben:Na dann korrigiere ich erstmal Deine Frage: "Ist es möglich Instanzmethoden zu einem Objekt hinzuzufügen?", denn an die Klasse möchtest Du die ja nicht binden.

der Punkt geht an Dich :)

BlackJack hat geschrieben:Das mit den Unter- und Obermengen ist nett, aber das unpythonische ist die Verwendung von `isinstance()`. Das muss ja wohl irgendwo verwendet werden um diesen ganz bestimmten Typ zu testen, ansonsten gäb's das Problem nicht und man könnte auch den quakenden Hund benutzen.

Der Punkt nicht. Ich habe nie behauptet, dass ich "instanceof" _verwende_, sondern dass es _möglich_ sein soll. Somit _kann_ das Problem bestehen, muss aber nicht. Wenn es entsteht, soll es transparent sein.

Wieso bietet Python eigentlich "unpythonische" Funktionen an? Kennen die Entwickler nicht die idiomatische Verwendung ihrer Sprache? Sollte man vielleicht van Russum zur Nachschulung schicken?
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Freitag 16. März 2007, 13:09

Wozu das immer auch gut ist... Wie wäre es damit:

Code: Alles auswählen

class X(object):
    def __init__(self, mode):
        if mode == 0:
            self.t = self.t_A
        else:
            self.t = self.t_B

    def t_A(self):
        print "A"

    def t_B(self):
        print "B"

x = X(0)
x.t() # => "B"

x = X(1)
x.t() # => "A"

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
hiasl
User
Beiträge: 31
Registriert: Donnerstag 20. April 2006, 13:36

Beitragvon hiasl » Freitag 16. März 2007, 13:09

Dill hat geschrieben:kennst du die artikel-serie:

http://www.onlamp.com/pub/a/python/2003 ... asses.html


Besten Dank, das war, was ich wollte :)
BlackJack

Beitragvon BlackJack » Freitag 16. März 2007, 14:02

hiasl hat geschrieben:
BlackJack hat geschrieben:Das mit den Unter- und Obermengen ist nett, aber das unpythonische ist die Verwendung von `isinstance()`. Das muss ja wohl irgendwo verwendet werden um diesen ganz bestimmten Typ zu testen, ansonsten gäb's das Problem nicht und man könnte auch den quakenden Hund benutzen.

Der Punkt nicht. Ich habe nie behauptet, dass ich "instanceof" _verwende_, sondern dass es _möglich_ sein soll.


Also wird es doch irgendwo verwendet, wäre dem nicht so, löst Du ein Problem das es nicht gibt.

Wieso bietet Python eigentlich "unpythonische" Funktionen an? Kennen die Entwickler nicht die idiomatische Verwendung ihrer Sprache?


Och bitte. Man kann so ziemlich jedes Feature zweckentfremden. "Pythonische" Verwendung von Instanzmethoden, die zur Laufzeit einem Objekt hinzugefügt werden, wäre zum Beispiel einem Hund, der nicht quaken kann, eine solche Methode dynamisch zu verpassen, damit er irgendwo als Ente durchgeht und nicht damit dort dann ein `instanceof(obj, Ente)` funktioniert.

Idiomatische Verwendung bedeutet ja gerade, dass es nicht von der Sprache so erzwungen wird, sondern dass etwas in der Regel so formuliert wird, weil es der Philosophie der Sprache entspricht. Die meisten Sachen kann man auch gar nicht erzwingen, weil sie formal gar nicht erfasst werden. Selbst bei statischeren Sprachen geht das nicht.

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder