@partial(property, ...)

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.
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

@partial(property, ...)

Beitragvon str1442 » Montag 23. März 2009, 21:22

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.
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Beitragvon Zap » Montag 23. März 2009, 21:52

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
DasIch
User
Beiträge: 2402
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Beitragvon DasIch » Montag 23. März 2009, 22:22

@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.
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

Beitragvon helduel » Dienstag 24. März 2009, 10:01

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
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Dienstag 24. März 2009, 10:24

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.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Beitragvon str1442 » Dienstag 24. März 2009, 19:00

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.

Wer ist online?

Mitglieder in diesem Forum: Bing [Bot]