Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Existiert ein Attribut?

0 views
Skip to first unread message

Ole Streicher

unread,
Oct 1, 2009, 8:32:24 AM10/1/09
to
Hallo,

ich möchte gerne die Antwort auf das Subject für ein bestimmtes Objekt
herausfinden :-)

t.m.: Ich habe ein Python-Objekt und möchte gerne wissen, ob es ein
bestimmtes Attribut besitzt. Wie mache ich das am effektivsten?

Die einfachste Variante ist

try:
myobjekt.myattribute
do_if_attribute_exists()
except AttributeError:
do_if_no_attribute()

aber das sieht (wieder mal) nicht sehr elegant aus.

Wie gehts besser?

Viele Grüße

Ole

Stefan Behnel

unread,
Oct 1, 2009, 9:47:50 AM10/1/09
to
Ole Streicher schrieb:
> Hallo,
>
> ich mᅵchte gerne die Antwort auf das Subject fᅵr ein bestimmtes Objekt
> herausfinden :-)
>
> t.m.: Ich habe ein Python-Objekt und mᅵchte gerne wissen, ob es ein

> bestimmtes Attribut besitzt. Wie mache ich das am effektivsten?
>
> Die einfachste Variante ist
>
> try:
> myobjekt.myattribute
> do_if_attribute_exists()
> except AttributeError:
> do_if_no_attribute()

Bei solchen Dingen ist Vorsicht geboten. Wenn im Aufruf von
do_if_attribute_exists() zufᅵllig irgendwo ein AttributeError fliegt, wird
anschlieᅵend (wahrscheinlich ungewollt) do_if_no_attribute() aufgerufen,
anstatt dich auf den Fehler aufmerksam zu machen.

Besser ist:

try:
myobjekt.myattribute
except AttributeError:
do_if_no_attribute()
else:
do_if_attribute_exists()


> aber das sieht (wieder mal) nicht sehr elegant aus.
>
> Wie gehts besser?

hasattr() ?

Stefan

Ole Streicher

unread,
Oct 1, 2009, 10:30:18 AM10/1/09
to
Hallo Stefan,

Stefan Behnel <stef...@behnel.de> writes:
>> Ich habe ein Python-Objekt und möchte gerne wissen, ob es ein


>> bestimmtes Attribut besitzt. Wie mache ich das am effektivsten?

> hasattr() ?

Danke. Manches ist eben einfach, wenn mans weiß :-)

Viele Grüße

Ole

Thomas Rachel

unread,
Oct 1, 2009, 10:39:03 AM10/1/09
to
Stefan Behnel schrieb:

> Besser ist:
>
> try:
> myobjekt.myattribute
> except AttributeError:
> do_if_no_attribute()
> else:
> do_if_attribute_exists()

ACK.

Das ist auch EAFP (http://wiki.python.de/Allgemeine%20Begriffe#E),
während...

>> aber das sieht (wieder mal) nicht sehr elegant aus.
>>
>> Wie gehts besser?
>
> hasattr() ?


...das LBYL (http://wiki.python.de/Allgemeine%20Begriffe#L) ist.


Thomas

Ole Streicher

unread,
Oct 1, 2009, 10:49:41 AM10/1/09
to
Hallo Thomas,

Thomas Rachel <nutznetz-drei-...@spamschutz.glglgl.net>
writes:
> Stefan Behnel schrieb:


>> try:
>> myobjekt.myattribute
>> except AttributeError:
>> do_if_no_attribute()
>> else:
>> do_if_attribute_exists()
> ACK.
> Das ist auch EAFP (http://wiki.python.de/Allgemeine%20Begriffe#E), während...

>> hasattr() ?

Hängt natürlich vom Zusammenhang ab. In meinem Fall habe ich "etwas" ('a'),
das in zwei Inkarnationen auftreten kann:

1. als Datentabelle, zugreifbar über die Arrays a.x, a.y.
2. als (potentiell teure) Funktion, zugreifbar mit y = a(x)

Alle, die damit umgehen, wissen, wie sie diese beiden Versionen
verarbeiten.

In der Anzeige will ich (aus Performancegründen) die Funktion jedoch
nicht haben. Da in Python Enten eben einfach Flügel und keinen Namenstag
haben (und das tatsächlich genau an dieser Stelle auch genutzt wird),
geht ein

if isinstance(a, DataTable): ...

nicht, sondern muss so ersetzt werden, dass die Funktion ausgeklammert
wird.

Also

if hasattr(a, 'x'): ...

Auch hier wieder die Frage: ist mein Ansatz verquer?

Viele Grüße

Ole

Marek Kubica

unread,
Oct 1, 2009, 12:33:12 PM10/1/09
to
On Thu, 01 Oct 2009 16:49:41 +0200
Ole Streicher <ole-use...@gmx.net> wrote:

> Hängt natürlich vom Zusammenhang ab. In meinem Fall habe ich
> "etwas" ('a'), das in zwei Inkarnationen auftreten kann:
>
> 1. als Datentabelle, zugreifbar über die Arrays a.x, a.y.
> 2. als (potentiell teure) Funktion, zugreifbar mit y = a(x)
>
> Alle, die damit umgehen, wissen, wie sie diese beiden Versionen
> verarbeiten.
>
> In der Anzeige will ich (aus Performancegründen) die Funktion jedoch
> nicht haben. Da in Python Enten eben einfach Flügel und keinen
> Namenstag haben (und das tatsächlich genau an dieser Stelle auch
> genutzt wird), geht ein
>
> if isinstance(a, DataTable): ...
>
> nicht, sondern muss so ersetzt werden, dass die Funktion ausgeklammert
> wird.
>
> Also
>
> if hasattr(a, 'x'): ...
>
> Auch hier wieder die Frage: ist mein Ansatz verquer?

Hmm, was du machen kannst, ist versuchen es als Funktion aufzurufen und
wenn das nicht klappt (es also nicht fliegt), dann auf deine Attribute
zuzugreifen. Ist eigentlich wie dein Attributzugriff, nur eben
andersrum.

Funktioniert natürlich nur solange wie die Funktion kein Attribut 'x'
hat oder andersrum solange dein Objekt mit Attribut 'x' nicht callable
ist, aber das würde ich dann eh als bösartigkeit werten :)

Es gibt dafür auch eigentlich keinen "kanonischen" Weg den "der
Python-Programmierer" gehen würde. Jede der Methoden hat Vor- und
Nachteile.

grüße,
Marek

Florian Diesch

unread,
Oct 1, 2009, 2:39:09 PM10/1/09
to
Ole Streicher <ole-use...@gmx.net> writes:


> H�ngt nat�rlich vom Zusammenhang ab. In meinem Fall habe ich "etwas" ('a'),


> das in zwei Inkarnationen auftreten kann:
>

> 1. als Datentabelle, zugreifbar �ber die Arrays a.x, a.y.


> 2. als (potentiell teure) Funktion, zugreifbar mit y = a(x)
>
> Alle, die damit umgehen, wissen, wie sie diese beiden Versionen
> verarbeiten.
>

> In der Anzeige will ich (aus Performancegr�nden) die Funktion jedoch
> nicht haben. Da in Python Enten eben einfach Fl�gel und keinen Namenstag
> haben (und das tats�chlich genau an dieser Stelle auch genutzt wird),


> geht ein
>
> if isinstance(a, DataTable): ...
>
> nicht, sondern muss so ersetzt werden, dass die Funktion ausgeklammert
> wird.
>
> Also
>
> if hasattr(a, 'x'): ...
>
> Auch hier wieder die Frage: ist mein Ansatz verquer?

Ich w�rde
if not callable(a):
vorziehen


Florian
--
<http://www.florian-diesch.de/software/pdfrecycle/>

Ole Streicher

unread,
Oct 1, 2009, 4:36:16 PM10/1/09
to
Hallo Florian,

Florian Diesch <die...@spamfence.net> writes:
>> In der Anzeige will ich (aus Performancegründen) die Funktion jedoch
>> nicht haben.
> Ich würde
> if not callable(a):
> vorziehen

Damit würde ich die Optimierung verhindern, dass eine Funktion eventuell
die Daten auch performant per Tabelle enthält (ggfs. in einer geringeren
Auflösung).

Viele Grüße

Ole

Mick Krippendorf

unread,
Oct 1, 2009, 5:29:26 PM10/1/09
to
Hallo.

Ole Streicher schrieb:


>
> In meinem Fall habe ich "etwas" ('a'),
> das in zwei Inkarnationen auftreten kann:
>
> 1. als Datentabelle, zugreifbar über die Arrays a.x, a.y.
> 2. als (potentiell teure) Funktion, zugreifbar mit y = a(x)

Das scheint mir das Liskov-Substitution-Principle zu verletzen: zwei
Objekte unterschiedlichen Typs sollen dasselbe tun (Daten zur Verfügung
stellen), aber man muss per Fallunterscheidung testen, wie man an diese
Daten gelangt. Richtig wäre, beide Objekte polymorph über dasselbe
Interface anzusprechen. In Java schriebe man für sowas blödsinnige
getter-Methoden, in Python verwendet man den property-Deskriptor:

class Dumb(object):
def __init__(self):
self.x = ...
self.y = ...

class Smart(object):
@property # builtin descriptor
def x(self):
return ... # kompliziert berechnetes zeugs
@property # builtin descriptor
def y(self):
return ... # kompliziert berechnetes zeugs

...

a = Dumb()
print a.x # die von x _referenzierten_ Daten werden ausgegeben
print a.y # dto. für y

a = Smart()
print a.x # die von x() _berechneten_ Daten werden ausgegeben
print a.y # dto. für y()


> Alle, die damit umgehen, wissen, wie sie diese beiden Versionen
> verarbeiten.

Möchte man hoffen...


> In der Anzeige will ich (aus Performancegründen) die Funktion jedoch
> nicht haben.

Das mit der Anzeige verstehe ich nicht. Im Übrigen sagt The Don:
premature optimization is the root of all evil


Gruß,
Mick.

Ole Streicher

unread,
Oct 2, 2009, 3:17:29 AM10/2/09
to
Hallo Mick,

Mick Krippendorf <mad....@gmx.de> writes:
>> In meinem Fall habe ich "etwas" ('a'), das in zwei Inkarnationen
>> auftreten kann:
>> 1. als Datentabelle, zugreifbar über die Arrays a.x, a.y.
>> 2. als (potentiell teure) Funktion, zugreifbar mit y = a(x)
> Das scheint mir das Liskov-Substitution-Principle zu verletzen: zwei
> Objekte unterschiedlichen Typs sollen dasselbe tun (Daten zur Verfügung
> stellen), aber man muss per Fallunterscheidung testen, wie man an diese
> Daten gelangt. Richtig wäre, beide Objekte polymorph über dasselbe
> Interface anzusprechen.

Gerne :-)

> class Smart(object):
> @property # builtin descriptor
> def x(self):
> return ... # kompliziert berechnetes zeugs
> @property # builtin descriptor
> def y(self):
> return ... # kompliziert berechnetes zeugs

Soo einfach ist es ja nicht: Eine Datentabelle hat diskrete
Funktionswerte an den definierten Stellen, eine Funktion hat Werte an
beliebigen Stellen. Welche da genommen werden, wird erst bei deren
Verwendung entschieden: beim Speichern in eine CSV-Datei genau die, wo
auch die Datentabelle Werte hat, bei der Anzeige in einem Diagram
natürlich auch die Zwischenpunkte (welche, hängt wiederum von der
Auflösung ab).

Das scheint mir schwer (und unsinnig) in ein gemeinsames Interface
pressbar.

>> Alle, die damit umgehen, wissen, wie sie diese beiden Versionen
>> verarbeiten.

> Möchte man hoffen...

Da Python keine Deklaration des Interfaces bei der Übergabe erlaubt,
bleibt tatsächlich nur Hoffen, Beten und Testen. Falls Du eine bessere
Idee hast: her damit.

>> In der Anzeige will ich (aus Performancegründen) die Funktion jedoch
>> nicht haben.

> Das mit der Anzeige verstehe ich nicht.

Funktionen und Daten werden in einem gemeinsamen Diagramm angezeigt. Das
geht auch hervorragend.

Wird die Maus über die Anzeige bewegt, dann sollen in einem extra
Fenster die zur Position gehörenden Werte angezeigt werden. Für die
Funktion dauert das (im Verhältnis zur Mausbewegung) sehr lange.

> Im Übrigen sagt The Don: premature optimization is the root of all
> evil

Was soll ich tun? Das Problem ignorieren? Das Tool ist unbenutzbar, wenn
das Update zu lange dauert. Also lautet die längerfristige Lösung:
optimieren der Anzeige (z.B. cachen aller Funktionswerte) und die
kürzerfristige: Abschalten der Anzeige für die Funktion.

Es gibt auch andere Stellen, wo man gerne eine entsprechende
Unterscheidung möchte: Daten kann man fitten, Funktionen nicht. Ein Fit
läuft in zwei Stufen ab:

1. Eingabe der (Start-) Parameter
2. der eigentliche Fit

Was bei einem Fit daneben geht, ist nicht die Eingabe der
Parameter, sondern der Fit selbst. Trotzdem möchte man natürlich
verhindern, dass man eine Dialogbox angezeigt bekommt, in der man eine
Funktion fitten kann, um dann danach einen "Ätsch! Geht gar
nicht!"-Fehler zu bekommen.

Das ist m.E. einer der Fälle, wo die Entschuldigung fehl am Platze wäre
und man vorher testen sollte.

Viele Grüße

Ole

Thomas Rachel

unread,
Oct 2, 2009, 3:31:50 AM10/2/09
to
Ole Streicher schrieb:

> Was bei einem Fit daneben geht, ist nicht die Eingabe der
> Parameter, sondern der Fit selbst. Trotzdem möchte man natürlich
> verhindern, dass man eine Dialogbox angezeigt bekommt, in der man eine
> Funktion fitten kann, um dann danach einen "Ätsch! Geht gar
> nicht!"-Fehler zu bekommen.
>
> Das ist m.E. einer der Fälle, wo die Entschuldigung fehl am Platze wäre
> und man vorher testen sollte.

Das stimmt.


Aber dann würde ich mir ein einheitliches Interface ausdenken, z.B. mit
den Attributen may_fit und do_fit und die Auswahl des "zu tuenden" eben
polymorpherweise dem Objekt überlassen.

Es sei denn, das sind fixe Objekte, die Du aus einer Library bekommst.
Aber auch da kannst Du

* Attribute "nachschieben"
* erben
* wrappen

und somit ein für Dich passendes Interfae generieren.

Thomas

Ole Streicher

unread,
Oct 2, 2009, 3:51:59 AM10/2/09
to
Hallo Thomas,

Thomas Rachel <nutznetz-drei-...@spamschutz.glglgl.net>
writes:


> Aber dann würde ich mir ein einheitliches Interface ausdenken, z.B. mit den
> Attributen may_fit und do_fit und die Auswahl des "zu tuenden" eben
> polymorpherweise dem Objekt überlassen.

Das ist die Frage, wessen Eigenschaft das ist.

Klar kann eine Datentabelle die Eigenschaft "may_fit" haben und eine
Funktion nicht -- das ist aber schwierig wartbar: morgen kommt jemand
und kann auch (bestimmte) Funktionen fitten; dann muss ich durch alle
Funktionen gehen und die als "may_fit_with_this_special_method"
markieren. Widerspricht m.E. dem Duck-Typing.

Also weiß der Fitter, was er fitten kann und was nicht, und er wird
vorher gefragt: in meinem Fall kann man fitten, wenn es x- und
y-Datenreihen gibt, also ist

def may_fit(data):
return has_attribute(data.x) and has_attribute(data.y)

und werauchimmer eine Idee hat, wie er anderes fittet, bastelt seine
eigene Methode zum Testen.

Viele Grüße

Ole

0 new messages