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

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

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: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

@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

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
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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

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.
Antworten