Seite 1 von 1
@partial(property, ...)
Verfasst: Montag 23. März 2009, 21:22
von str1442
Code: Alles auswählen
In [11]: from functools import partial
In [12]: class A(object):
....: def __init__(self):
....: self.var = 0
....: @partial(property, lambda self: self.var)
....: def p_var(self, value):
....: self.var = value % 16
....:
....:
In [14]: a = A()
In [15]: a.p_var
Out[15]: 0
In [16]: a.p_var = 50
In [17]: print a.p_var
2
Würdet ihr dieses Muster benutzen? Das spart zwar die nervigen Billig Get/Set Methoden und ist auch logisch, aber sieht doch irgendwo... magic aus. Und wenn man so an die Sache rangeht kann man auch gleich sich mit partial alles und jedes zu Dekoratoren zusammenstöpseln.
Verfasst: Montag 23. März 2009, 21:52
von Zap
Was mich daran stört ist das man eine Methode definiert die sich wie eine Variable verhält.
Da finde ich den reinen @property Ansatz sauberer
Verfasst: Montag 23. März 2009, 22:22
von DasIch
@Zap Der Sinn von property ist dass man eine Methode hat die sich wie eine Variable verhält.
Also ich sehe da jetzt nichts magisches. Auf den ersten Blick vielleicht ungewöhnlich aber mehr auch nicht.
Verfasst: Dienstag 24. März 2009, 10:01
von helduel
Moin,
dadurch ist nichts wirklich gewonnen. Eine triviale Getter-Funktion muss ich ja trotzdem schreiben (hier halt lambda). Dazu kommt, dass wohl jeder, der das sieht, erstmal überlegen muss, was hier passiert. Da finde ich den "Standard-Property-Weg" auch eleganter.
Gruß,
Manuel
Verfasst: Dienstag 24. März 2009, 10:24
von Leonidas
Man könnte das Lamda auch durch ``operator.attrgetter('var')`` ersetzen, dann hat man keine Funktion eigens definiert. Finde ich auch besser als das Lambda hier.
Verfasst: Dienstag 24. März 2009, 19:00
von str1442
Morgen,
operator.attrgetter() ist eine gute Idee. Aber mir ging es auch um den Gebrauch des Dekorators hier. Man könnte zum Beispiel auch sowas hier machen:
Code: Alles auswählen
In [28]: class Auto(object):
....: def __init__(self, name, tank, fuel_function):
....: self.name = name
....: self.tank = tank
....: self.fuel_function = fuel_function
....:
....:
In [29]: from functools import partial
In [30]: @partial(Auto, "Bla", 200)
....: def auto_instance(x):
....: return 2*x
....:
In [31]: print auto_instance
<__main__.Auto object at 0xb7cc084c>
Das ist dann aber definitiv nicht mehr der Sinn eine Dekorators (sofern ich plane, das Auto wie ein "reguläres" Objekt zu benutzen und anfange solche Dekoratoren in irgendwelche auto_factory() Funktionen zu stecken). Der Funktionsname hat mit dem Verhalten nichts zu tun, und das funktioniert so auch nur wegen Ducktyping (was ja auch gut so ist).
Die partial/property Variante finde ich nun insoweit unschön, das es schon in diese Richtung geht, schlussendlich kann ich mit partial alles irgendwie zu einer Art Dekorator umbauen, was ein Callable als Argument entgegennimmt. Ich muss zwar nur eine Methode wirklich implementieren, diese ist aber nicht der "Setter", sondern nach der herauskommenden Variable benannt. Bei einem normalen @property ist das noch recht vertretbar, da der Attributsname schon eine gewisse Aussagekraft über das Tun des "Getter" Properties hat. (Wenn ich also einen Getter für ein Attribut "position" (oder was auch immer) schreiben würde, sagt position im Grunde schon aus, das sich hinter dem folgenden Code die Position verbirgt, nur diese eben berechnet wird. Bei einem Setter müsste die Methode aber zumindest "set_position" heissen).
Das Konstrukt an sich ist eigentlich relativ einfach, aber die Verwendung von einem Partial Objekt als Dekorator in dieser Art und Weise fühlt sich für mich einfach unsauber an.
ADD:
auto_factory:
Code: Alles auswählen
def auto_factory(name, tank, a):
@partial(Auto, name, tank)
def auto_inst(x):
return 2*a*x
return auto_inst
Nur um nochmal auf die auto_factory zu verdeutlichen.