Seite 1 von 1
Konfiguration von Objekten innerhalb einer Klasse
Verfasst: Samstag 1. August 2009, 14:41
von ippurk
Hallo zusammen,
ich hab hier mal was produziert:
Code: Alles auswählen
class Home():
"""
This is a home
"""
def __init__(self):
pass
def configure(self, **args):
if "street" in args:
self.street = args["street"]
else:
self.street = None
if "nr" in args:
self.nr = int(args["nr"])
else:
self.nr = None
if "postcode" in args:
self.postcode = args["postcode"]
else:
self.postcode = None
if "city" in args:
self.city = args["city"]
else:
self.city = None
def show_address(self):
print self.street + " " + str(self.nr)
print str(self.postcode) + " " + self.city
if __name__ == "__main__":
home1 = Home()
home1.configure(street="Highway",
nr=12,
postcode=45321,
city="Big City")
home1.show_address()
Ich weiß, dass ich die einzelnen Werte der Variablen auch ändern könnte, indem ich
schreibe, aber so kommt mir das irgendwie praktischer vor. Was meint ihr ?
Verfasst: Samstag 1. August 2009, 14:51
von cofi
Variable Argumente sind eine nette Sache, aber nur selten wirklich benoetigt und verschleiern zudem die Parameter, die die Funktion wirklich entgegen nimmt.
In deinem Fall kannst du auch einfach
Code: Alles auswählen
def __init__(self, street=None, nr=None, postcode=None, city=None):
schreiben, zumal der Schritt ueber ``configure`` IMHO sinnfrei ist. Praktischer ist der Weg ueber die Initialsierung, solltest du aber dennoch Datensaetze/Objekte haben die sich haeufiger und komplett aendern, kannst du sie trotzdem anbieten - ist letzteres nicht erfuellt ist der direkte Zugriff auf die Attribute weit sauberer.
Btw: ``**args`` heisst konventionell ``**kwargs``, ``args`` nimmt man fuer die Postionsargumente. Und von ``object`` erben sollte man in Python2.x auch

Verfasst: Samstag 1. August 2009, 15:06
von sma
ippurk, du kannst `__init__` und `configure` kombinieren und das ganze wesentlich einfacher gestalten. Mit `fromkeys` kannst du ein dict mit einer Liste von Schlüsseln initialisieren, sodass deren Werte `None` sind. Wenn du das an `__dict__` zuweist, hast du automatisch alle deine gewünschten Properties angelegt. Mit `update` kannst du ein dict (also z.B. das mit deinen Properties) mit den Schlüsseln und Werten aus dem angegebenen dict aktualisieren.
Code: Alles auswählen
class Home(object):
def __init__(self, **kw):
self.__dict__ = dict.fromkeys("street city".split())
self.__dict__.update(kw)
h = Home(city="Kiel")
print h.street
print h.city
Stefan
Verfasst: Samstag 1. August 2009, 15:31
von Darii
sma hat geschrieben:Wenn du das an `__dict__` zuweist, hast du automatisch alle deine gewünschten Properties angelegt. Mit `update` kannst du ein dict (also z.B. das mit deinen Properties) mit den Schlüsseln und Werten aus dem angegebenen dict aktualisieren.
Bloß nicht. Wenn schon Magie, dann auf dem „offiziellen“ Weg.
Code: Alles auswählen
class Home(object):
def __init__(self, **attributes):
for attr in ("street", "nr", "postcode", "city"):
setattr(self, attr, attributes.get(attr, None))
Wenn man direkt auf __dict__ zugreift, dann umgeht man damit eventuell existierende Properties etc.
Verfasst: Samstag 1. August 2009, 19:14
von ippurk
hm ja, verstehe. Kommt mir auch im Nachhinein relativ umständlich vor das ganze. Ich werd wohl cofis ersten Vorschlag nutzen. Die Idee kam wahrscheinlich daher, daß ich in den letzten Wochen recht viel mit Tkinter gemacht habe. Da schreibt man ja auch immer configure.
Auf jeden Fall Danke für die Erläuterungen.
Verfasst: Samstag 1. August 2009, 20:26
von BlackJack
@ippurk: Bei `Tkinter` liegt das `Tk`, das ist halt so entworfen und die Python-Schnittstelle ist nur eine relativ dünne Schicht über diese API.
Verfasst: Sonntag 2. August 2009, 08:00
von sma
Darii hat geschrieben:Bloß nicht. Wenn schon Magie, dann auf dem „offiziellen“ Weg.
__dict__ ist Teil der Sprachspezifikation. Ich sehe nicht, was daran magisch sein soll. Properties bei der Initialisierung zu umgehen kann ein Feature sein. Ich würde auch in Java in einem Constructor niemals die Setter-Methoden benutzen.
Stefan
Verfasst: Sonntag 2. August 2009, 08:26
von BlackJack
@sma: Die Unterstriche kennzeichnen es als "magisch", und man sollte so etwas nur verwenden, wenn es keine andere Alternative gibt.
Niemals Setter aus dem Konstruktor aufzurufen oder äquivalent dazu in Python den Weg über die externe API eines Objekts zu meiden ist IMHO keine gute Idee. Angenommen ein Setter bzw. bei Python ein Property macht etwas wichtiges mit dem Wert der gesetzt werden soll, dann müsste man den Code dafür duplizieren wenn man im Konstruktor das gleiche ohne den Setter erreichen will.
Verfasst: Sonntag 2. August 2009, 19:19
von Darii
sma hat geschrieben:Darii hat geschrieben:Bloß nicht. Wenn schon Magie, dann auf dem „offiziellen“ Weg.
__dict__ ist Teil der Sprachspezifikation. Ich sehe nicht, was daran magisch sein soll. Properties bei der Initialisierung zu umgehen kann ein Feature sein. Ich würde auch in Java in einem Constructor niemals die Setter-Methoden benutzen.
Wenn du eine Property umgehen *willst*, sprichst auch nichts gegen ``__dict__``, bloß wenn du es nur einfach so benutzt, kann das unerwartete Nebeneffekte haben. Beispielsweise erkennt der sqlalchemy-Mapper Änderungen am Objekt nicht über ``__dict__`` sondern über Properties, wenn man das nicht bedenkt/weiß darf man da u.U. unnötig lange nach Fehlern suchen.
Hat mich jedenfalls mal über eine Stunde gekostet herauszufinden, warum die Relations die ich über ``__dict__`` in einem Kontruktor gesetzt hatte nicht gespeichert wurde, der Rest den ich über ``instance.attribue = foo`` gesetzt hatte, aber schon. Und das nur weil ich dachte, „Kannst ja auch einfach ``self.__dict__.update(kwargs)`` machen“. Meine Lehre daraus: Finger Weg von __*__ es sei denn, es geht nicht anders.