Welche Funktion hat der Befehl getattr?

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
Monsi
User
Beiträge: 23
Registriert: Mittwoch 4. Februar 2009, 10:29

Donnerstag 12. Februar 2009, 12:00

Hallo,

ich bin ein totaler Programmier-Neuling und beschaeftige mich seit ein paar Tagen mit Python. Hauptsaechlich hangel ich mich an dem Tutorial von Mark Pilgrim entlang, was auch ganz gut funktioniert...allerdings wird mir nicht so richtig klar, was

Code: Alles auswählen

getattr
fuer eine funktion hat.

Also wenn ich beispielsweise sage

Code: Alles auswählen

getattr(li, "append")("Moe")
wird meine Liste li durch Moe erweitert. Aber wo ist der Unterschied zu dem Befehl

Code: Alles auswählen

li.append("Moe")
? Und was macht z.B.

Code: Alles auswählen

getattr(object, method)
in einer Funktion? Und wie kann man

Code: Alles auswählen

 getattr
als Dispatcher benutzen (was ist ueberhaupt ein Dispatcher)?

Ich hoffe ich habe mich einigermassen verstaendlich ausgedrueckt und jemand kann mir helfen...ich habe so eine Ahnung, wie das Ganze funktioniert, aber ich kann es nicht in gute Worte fassen. Ich waere sehr dankbar fuer eine einleuchtende Erklaerung.

Liebe Gruesse, Katharina
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Donnerstag 12. Februar 2009, 13:16

Hallo Monsi, willkommen im Forum,
Monsi hat geschrieben:Hauptsaechlich hangel ich mich an dem Tutorial von Mark Pilgrim entlang, was auch ganz gut funktioniert...
Gute Wahl! Ich hätte es nicht unbedingt für Anfänger empfohlen, aber wenn du damit schon zurecht kommst - um so besser.
Monsi hat geschrieben:Also wenn ich beispielsweise sage

Code: Alles auswählen

getattr(li, "append")("Moe")
wird meine Liste li durch Moe erweitert. Aber wo ist der Unterschied zu dem Befehl

Code: Alles auswählen

li.append("Moe")
?
Es gibt keinen Unterschied. ``getattr()`` ist dazu da auf Attribute zuzugreifen wenn du ein Objekt hast (wie ``li``) und den Namen vom Attribut als String. Nehmen wir an du willst die Attribute eines bekannten Objektes aus einer Konfigurationsdatei im INI-Format setzen:

Code: Alles auswählen

[Config]
attibut=wert
Dann hast du beim Einlesen "attribut" als String. Wenn du auf dieses Attribut zugreifen willst, funktioniert ``configuration."attribut"`` ja nicht, daher musst du dann ``getattr()``nutzen.
Monsi hat geschrieben:Und was macht z.B.

Code: Alles auswählen

getattr(object, method)
in einer Funktion?
Das gleiche. ``object`` ist eine Referenz auf ein Objekt und ``method`` ist ein String mit dem Namen eines Attributes.
Monsi hat geschrieben:Und wie kann man

Code: Alles auswählen

 getattr
als Dispatcher benutzen (was ist ueberhaupt ein Dispatcher)?
Dispatch bedeutet, dass du einen Aufruf machst, zum Beispiel ``katze.sag_was()`` und der Dispatcher dann feststellt welches ``sag_was`` benutzt werden soll. Wenn ``katze`` ein ``sag_was`` Attribut hat, wird das verwendet, wenn nicht, dann wird in der Elternklasse geschaut usw. Man kann sich in Python mittels ``__getattr__`` und ``__getattribute__`` in die Funktionsweise des Dispatchers einklinken und modifizieren wie das funktioniert - das wird aber höchstwahrscheinlich für dich momentan eher unwichtig sein.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Monsi
User
Beiträge: 23
Registriert: Mittwoch 4. Februar 2009, 10:29

Donnerstag 12. Februar 2009, 14:11

Vielen Dank fuer die schnelle Antwort! Ja, so in etwa habe ich mir das gedacht...also ist getattr nuetzlich, wenn ich noch nicht genau weiss, welche Attribute verfuegbar sind? Also dass ich etwas als string angebe, von dem ich vermute, dass es ein Attribut ist, ohne zu wissen, ob es das tatasaechlich ist und wenn meine Funktion dann laueft, entscheidet sich ob das Attribut verfuegbar ist und wenn ja, wird es gleich angewendet. Ist das so korrekt?
Benutzeravatar
snafu
User
Beiträge: 5492
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Donnerstag 12. Februar 2009, 14:27

Monsi hat geschrieben:also ist getattr nuetzlich, wenn ich noch nicht genau weiss, welche Attribute verfuegbar sind?
Nicht-Verfügbarkeit wirft einen AttributeError. Es ist eher umgekehrt: Du weißt beim Programmieren nicht, welches Attribut während der Programmausführung abgefragt werden soll. Wie Leonidas schon sagte: Wenn das Attribut z.B. in einer Datei steht und du eben den Inhalt der Datei nicht kennst, sondern nur sagst: "Was auch immer da steht - Greife darauf zu". Denn was aus der Datei ausgelesen wird, kommt ja als String an und kann dann nur mit getattr() angewendet werden.

Nehmen wir an, du bindest es beim Auslesen an "attr_from_config" und dort steht halt jetzt ein beliebiges Attribut drin, welches in einer anderen Datei an die dafür vorgesehene Stelle geschrieben wurde. Wenn du das Attribut nun abfragst, möchtest du ja nicht ein Attribut namens "attr_from_config" abfragen, sondern eben das was dahinter steckt.
shcol (Repo | Doc | PyPi)
Monsi
User
Beiträge: 23
Registriert: Mittwoch 4. Februar 2009, 10:29

Donnerstag 12. Februar 2009, 14:50

ich kriege langsam einen knoten im kopf :roll: also ich schreibe hier mal die beispielfunktion rein, wo getattr drin auftaucht. es wuerde mir unglaublich helfen, wenn ihr mir schreiben koenntet, was diese funktion genau macht. also was das ergebnis ist, weiss ich, aber wie die einzelnen elemente zum ergebnis beitragen und insbesondere die getattr-funktion ware gut zu wissen. den grossteil der funktion verstehe ich auch, aber bis eben dachte ich auch, ich haette getattr verstanden und nun bin ich wieder verwirrt.

also wir haben eine funktion die so aussieht:

Code: Alles auswählen

def info(object, spacing=10, collapse=1):
	"""Print methods and doc strings.

	Takes module, class, list, dictionary, or string."""
	methodList = [e for e in dir(object) if callable(getattr(object, e))]
	processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
	print "\n".join(["%s %s" %
					 (method.ljust(spacing),
					  processFunc(str(getattr(object, method).__doc__)))
					 for method in methodList])

if __name__ == "__main__":
	print help.__doc__
wenn ich jetzt sage

Code: Alles auswählen

li=[] 
und

Code: Alles auswählen

info(li)
, dann bekomme ich eine liste von Attributen, die ich fuer eine liste ausfuehren kann. das verstehe ich ja auch im groben und ganzen, aber koennt ihr mir an diesem konkreten beispiel sagen, wie getattr vorgeht? ich hoffe ich stehe hier nicht total auf dem schlauch...anscheinend ist das ja eins der kleineren verstaendnisprobleme die man hier haben kann, aber wie gesagt ich habe bis jetzt noch nie eine programmiersprache benutzt...
Monsi
User
Beiträge: 23
Registriert: Mittwoch 4. Februar 2009, 10:29

Donnerstag 12. Februar 2009, 15:23

ich habs eben noch mal mit selbsterklaerung versucht und ich denke ich habe eine gute vorstellung davon, was diese funktion macht. selbst schreiben koennte ich sie wohl nicht, aber ich denke das kommt mit der uebung. falls jemand die musse haben sollte mir trotzdem die funktion schritt fuer schritt zu erklaren darf dies gerne tun, dann kann ich vergleichen, ob meine ueberlegungen diesmal korrekt waren. ansonsten erst mal vielen dank fuer die hilfreichen kommentare
DasIch
User
Beiträge: 2462
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Donnerstag 12. Februar 2009, 15:55

Im Prinzip ist es einfach. In Python ist alles was sich zuweisen lässt ein Objekt. Objekte haben Attribute, einige davon sind aufrufbar, das sind die Methoden eines Objekts. Methoden haben einen sogenannten docstring, indem i.d.R. steht wofür die Methode da ist, was sie macht und wie sie zu verwenden ist. Diesen wollen wir haben.

Als erstes brauchen wir also alle Methoden. Wir fangen an mit dir, dir liefert alle Namen der Attribute eines Objekts zurück, um zu prüfen ob ein Attribut aufrufbar ist brauchen wir aber das Attribut. Das Problem löst man indem man mit getattr das Attribut bekommt und mit callable prüft ob dieses aufrufbar ist.

Jeder Name in der ermittelten Liste wird dann einfach ausgegeben sowie der docstring der Methode, der versteckt sich übrigens hinter dem __doc__ Attribut.

processFunc ist nur zur Formatierung dar und nicht wirklich notwendig.
Monsi
User
Beiträge: 23
Registriert: Mittwoch 4. Februar 2009, 10:29

Donnerstag 12. Februar 2009, 16:07

wunderbar, so hatte ich es mir auch erklaert. also hab ich heute doch noch was gelernt :D vielen dank fuer deine erklaerung
Antworten