Seite 1 von 2

OO-Prinzipien und Python

Verfasst: Mittwoch 28. Januar 2009, 14:33
von Marky
Hallo zusammen,

ich finde übrigens, man sollte zu dem Thema OO-Design und Python ein eigenes Forum aufmachen :wink:
Aber jetzt meine Frage mit der Hoffnung auf Meinungen dazu.
Ich befinde mich in einem Modul A in dem ein Objekt einer Klasse erzeugt wird. Bei der Instanziierung wird als Konstruktor-Parameter eine Methode aus einem anderen Modul B übergeben, die per

Code: Alles auswählen

from B import method
bekannt gemacht wird.
Ich hoffe das ist durch meine Erklärung erstmal soweit verstanden.
Ich hab' ja mittlerweile eingesehen, dass man pythonisch denken soll :roll:
Ich glaube, man wollte wohl Code-Duplizierung verhindern oder gemeinsamen Code auslagern. Ich frage mich jetzt nur, ob das pythonisch ist oder eher schlechtes Code-Design?
Ich denke, sowas könnte man ja auch mit Hilfe einer Delegation an die entsprechende Klasse lösen. Mich kommt sowas vor, wie "durch die Brust ins Auge". Lasse mich aber gerne von dem Nutzen und den Vorteilen solcher Konstrukte überzeugen und vor dem Hintergrund guten und wartbaren Code zu erzeugen.
Ich meine ... machbar ist das, aber ist es auch sinnvoll? Das sollte jetzt übrigens keine rhetorische Frage sein...
Was meinen denn die Python-Freunde dazu ...?

Verfasst: Mittwoch 28. Januar 2009, 14:44
von Leonidas
IMHO ist es durchaus gut, dem Konstruktor irgedwelche Methoden als Parameter zu geben, wenn sie noetig sind.

Aber mit so wenig Code kann man schwer sagen, ob man dein Problem nun besser loesen kann oder nicht.

Verfasst: Mittwoch 28. Januar 2009, 14:46
von Marky
Kannst Du mir Beispiele nennen, wo es Sinn macht/machen könnte ?

Verfasst: Mittwoch 28. Januar 2009, 15:10
von helduel
Marky hat geschrieben:Kannst Du mir Beispiele nennen, wo es Sinn macht/machen könnte ?
Man könnte z.B. irgendwelchen Views auf Daten dadurch einen Sortier- oder Filter-Algorithmus mitgeben - je nachdem, was gerade nötig ist.

Die sort-Methode bei Listen akzeptiert eine Funktion, die dann entscheidet, wie genau sortiert wird. Oder auch die sub-Methode bei Regulären Ausdrücken nimmt eine Funktion, die dann je nach Treffer andere Strings zum ersetzen liefert. Gibt viele Möglichkeiten.

Verfasst: Mittwoch 28. Januar 2009, 15:23
von Marky
ok, leuchtet mir so langsam ein. Was die sort-Funktionalität angeht, gibt es sowas ähnliches in Java ja auch, indem man bestimmten Klassen eine Comparator-Instanz übergeben kann.
Hier sind dann zusätzlich auch Methoden möglich... ok ...

Verfasst: Mittwoch 28. Januar 2009, 15:41
von Leonidas
In Java werden Klasseninstanzen uebergeben, weil es keine First Class Functions gibt und Klassen keine Objekte sind, die man herumreichen koennte.

Verfasst: Mittwoch 28. Januar 2009, 16:23
von BlackJack
Ich verstehe den Ausgangsbeitrag nicht so ganz. Aus dem Modul `B` wird keine Methode, sondern eine Funktion importiert, oder allgemein gesprochen wohl ein "callable".

Sinnvolle Beispiele: Überall wo man unter bestimmten Umständen einen Rückruf von dem Objekt haben möchte, dass man da erstellt, oder wo das Objekt später diese Funktion aufrufen möchte um zum Beispiel andere Objekte zu erstellen.

Verfasst: Donnerstag 29. Januar 2009, 12:11
von bords0
BlackJack hat geschrieben:Ich verstehe den Ausgangsbeitrag nicht so ganz. Aus dem Modul `B` wird keine Methode, sondern eine Funktion importiert, oder allgemein gesprochen wohl ein "callable".
Woher weißt du, dass method callable ist? Vom Namen her?
Woher weißt du, dass method keine Methode ist?

Verfasst: Donnerstag 29. Januar 2009, 12:21
von Leonidas
bords0 hat geschrieben:Woher weißt du, dass method callable ist? Vom Namen her?
Von deiner Beschreibung.
bords0 hat geschrieben:Woher weißt du, dass method keine Methode ist?
Weil man keine Methoden importieren kann sondern nur Module, Klassen und Funktionen.

Verfasst: Donnerstag 29. Januar 2009, 12:42
von bords0
Leonidas hat geschrieben:
bords0 hat geschrieben:Woher weißt du, dass method callable ist? Vom Namen her?
Von deiner Beschreibung.
Ich hab doch noch gar nix geschrieben... und der OP hatte explizit Methode geschrieben, wenn du das nicht anerkennst, wie kommst du dann auf callable?
Leonidas hat geschrieben:
bords0 hat geschrieben:Woher weißt du, dass method keine Methode ist?
Weil man keine Methoden importieren kann sondern nur Module, Klassen und Funktionen.
Steht so ein Unsinn irgendwo in der Doku? Das sollte man melden. Es ist überhaupt kein Problem, Methoden zu importieren:

Code: Alles auswählen

>>> class A(object):
	def bla(self):
		pass

	
>>> method1 = A.bla
>>> method2 = A().bla
>>> from __main__ import method1 as m1, method2 as m2
>>> m1
<unbound method A.bla>
>>> m2
<bound method A.bla of <__main__.A object at 0x023991B0>>
>>> 

Verfasst: Donnerstag 29. Januar 2009, 13:10
von keppla
Leonidas hat geschrieben:
bords0 hat geschrieben:Woher weißt du, dass method keine Methode ist?
Weil man keine Methoden importieren kann sondern nur Module, Klassen und Funktionen.
Steht so ein Unsinn irgendwo in der Doku? Das sollte man melden. Es ist überhaupt kein Problem, Methoden zu importieren: [...]
Ich glaube, er wollte darauf raus, dass es nicht in der Form

Code: Alles auswählen

from module.classname import mehtod
geht, oder allgemeiner, dass man mit import nur an objekte kommt, die auf Modulebene einen Namen haben.

Verfasst: Donnerstag 29. Januar 2009, 13:18
von Marky
immer locker bleiben :wink: stimmt ja schon, dass man sich präzise ausdrücken sollte. Da ich von Java komme ist für mich alles eine Methode.
In Python wird da ja unterschieden.
Im konkreten Fall also, handelt es sich um eine Funktion.

Verfasst: Donnerstag 29. Januar 2009, 13:23
von Leonidas
Marky hat geschrieben:Da ich von Java komme ist für mich alles eine Methode.
In Python wird da ja unterschieden.
Eigentlich unterscheide ich da nicht. Es sind beides Funktionen und manchmal sind sie an Klassen gebunden, es sind aber dennoch Funktionen die die Instanz der Klasse als Parameter mitbekommen. Mehr nicht.

Verfasst: Donnerstag 29. Januar 2009, 13:30
von Marky
na ja ... du vielleicht nicht, andere schon:

http://openbook.galileocomputing.de/pyt ... 12_001.htm

Wenn man aus objektorientierter Sicht das Ganze betrachtet, hat eine Klasse für mich Methoden und keine Funktionen.
Funktionen bringe ich mit prozeduraler Programmierung in Verbindung.
Aber sei's drum...

Verfasst: Donnerstag 29. Januar 2009, 13:51
von Leonidas
Marky hat geschrieben:na ja ... du vielleicht nicht, andere schon:
Das Buch ist halt von Java-Programmierern geschrieben worden, die von Python nicht so die Ahnung haben. Siehe Kritik zu dem Buch im Forum.

Funktionen bringe ich persönlich eher mit Funktionaler Programmierung in Verbindung. Das mache ich in Python aber auch recht gerne.

Aus Objektorientierter Sicht gesehen hast du in einem Objekt in Python nur Attribute. Diese sind eben Callable (das was du als Methoden bezeichnest, Funktionen, es könnten aber theoretisch auch Klassen sein) oder nicht (also Properties und generell Objekte die kein ``__call__`` implementieren).

Argh, meine Erklärung ist irgendwie unklar.. mal sehen, vielleicht erklärt es jemand besser.

Verfasst: Donnerstag 29. Januar 2009, 14:46
von Darii
Leonidas hat geschrieben:Argh, meine Erklärung ist irgendwie unklar.. mal sehen, vielleicht erklärt es jemand besser.
Ich probiere es mal. :)

Code: Alles auswählen

foo.bar()
Ist die abkürzende Schreibweise von:

Code: Alles auswählen

getattr(foo, "bar")()
Dabei ist egal ob bar jetzt eine Funktion/Methode, ein beliebiges Objekt oder Klasse ist, Hauptsache bar ist "callable".

Und ob man jetzt

Code: Alles auswählen

class Foo:
    class bar: pass
foo = Foo()
print foo.bar()
noch als astreinen Methodenaufruf bezeichnen kann...

Verfasst: Donnerstag 29. Januar 2009, 14:48
von Marky
... ist fraglich.
Verstehe.

Verfasst: Donnerstag 29. Januar 2009, 14:56
von Leonidas
Zudem man noch Funktionen an Klassen binden kann, die vorher nicht Teil der Klasse waren.

Code: Alles auswählen

class A(object):
    pass

def foo(self):
    print "Methode der Instanz", self

A.foo = foo
a = A()
a.foo()
foo(a)
Da jetzt speziell zwischen Methode und Funktion zu unterscheiden scheint mir etwas künstlich. Natürlich, durch das binden an eine Klasse passiert etwas Magie, aber das ist mir zu verschwommen um da exakt unterscheiden zu wollen.

Verfasst: Donnerstag 29. Januar 2009, 20:15
von bords0
Leonidas hat geschrieben:Da jetzt speziell zwischen Methode und Funktion zu unterscheiden scheint mir etwas künstlich.
Warum machst du dann beim Importieren diesen Unterschied, d.h. behauptest, dass Funktionen importiert werden können, Methoden aber nicht? :?

Verfasst: Donnerstag 29. Januar 2009, 20:46
von str1442
Man kann nur Dinge direkt aus dem Modul Namespace importieren. Da Methoden nunmal im Namespace einer Klasse definiert sind, kann man sie nicht importieren. Das trifft auch auf jedes andere Objekt zu, das nicht direkt im Modul Namespace liegt.

Du musst einfach Python's Klassenkonzept verstehen:

Die Methoden einer Python Klasse sind eigentlich Funktionen. Du gibst das "self" bei einer Methode nicht umsonst ein! Ein Aufruf der Form:

Code: Alles auswählen

a.b(args)
einer Instanz a wird konvertiert in das hier:

Code: Alles auswählen

a.__class__.b(a, args)
Deswegen gibt man das self an. Es gibt keinen Unterschied zwischen einer Methode und einer Funktion, außer dem, das eine an eine solche Methode immer die eigene Instanz als erstes Argument überliefert bekommt. Du könntest die Methode auch direkt über a.__class__.b aufrufen, und ihr irgendetwas anderes mitgeben, das als self behandelt werden soll.

Weiters, eine Funktion ist "nur" ein callable. Callable ist jedes Objekt, das eine __call__ Methode besitzt. Mach doch mal dir() auf eine Funktion. Du kannst jedes Spezialverhalten in Python durch __doubleunderscore__ Methoden emulieren, es gibt keine "bevorzugten" Objekte. Selbst Klassen sind Objekte, und bei der Instanziierung einer Klasse wird deren eigene __call__ Methode aufgerufen. (Deswegen hat bei solchen Metaklassen genannten Klassen das überschreiben von __call__ lustige Effekte).