@ Function Decorators und any() und ...

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.
Crazed
User
Beiträge: 171
Registriert: Sonntag 18. Mai 2008, 11:44

Mittwoch 6. August 2008, 19:39

Hallo,
Ich habe (leider) erst letztens von den Funktions Dekoratoren gehört. Eine Frage vorweg wie lange gibt es die schon?

Und nun zur eigentlichen Thematik. Funktionsdekoratoren sind genaugenommen nur Funktionen die eine andere Funktion in sich kapseln z.b

Code: Alles auswählen

class Test(object):
    def __init__(self, val1, val2)
        self.val1 = val1
        self.val2 = val2

    @property # macht den zugriff Test.add möglich
    def add(self):
        return self.val1 + self.val2

    @staticmethod #macht self überflüssig
    def hallo():
        print 'Hello World'
>>> x = test(5,10)
>>> print x.add
15
Sollte circa so stimmen...
Also wie ich das jetzt verstanden haben sind property und staticmethod schon-existierende funktions dekoratoren mit einer bestimmten Funktion.
@property ermöglicht es beim Aufrufen einer bestimmten Funktionen es wie bei einer Variable zu machen

z.b:

Code: Alles auswählen

print Test.add
Wie funktioniert das? Wird eine neue variable erstellt mit dem gleichen namen der funktion und von dieser neu erstellten variable __call__ o.ä verändert?

Und der 2te Dekorator @staticmethod den gibt es ja eigentlich nur damit man sich self sparen kann oder? Wie funktioniert dieser?

Außerdem kann ich irgendwie nichts vernünftiges zu any() finden. Könnte mir da auch jemand eine Referenz geben bzw. mir das genauer erklären?

Noch eine letzte Frage:

geht folgendes bei prinzipiell jeder zuweisung?:

Code: Alles auswählen

test = [x for x in z]
Dabei wird innerhalb der brackets der Befehl ausgeführt und die verkürzte for schleife weist dabei der liste x immer den neuen wert von x zu bzw. hängt an, richtig?

Tut mir Leid, sind sicher dumme Fragen bei aber irgendwie verstehe ich es einfach nicht und ich bin mir sicher mit @property etc. lassen sich schöne dinge machen genauso wie mit any() und [x for x in z]

MfG,
CracKPod
Zuletzt geändert von Crazed am Mittwoch 6. August 2008, 20:27, insgesamt 1-mal geändert.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Mittwoch 6. August 2008, 19:56

Ich greife mal ein paar Punkte heraus:

property ist eigentlich kein decorator, sondern eine build-in-function.

Beispiel (mit nur zwei Argumenten - es gibt noch weitere -> siehe Doku):

Code: Alles auswählen

bgcolor = property(getbgcolor,setbgcolor)
Damit erreicht man, dass auf das Attribut bgcolor wie auf ein Datenattribut z.B. mit direkten Zuweisungen zugegriffen werden kann.
Während bei einem echten Datenattribut damit evtl. Nachteile verbunden sein können (keine Prüfung der Werte bei Zuweisung), kann man das über die getter-/setter abfangen, ohne diese dann auch tatsächlich verwenden zu müssen.

Ich persönlich finde das sehr schick.

@staticmethod ist ein decorator.
Damit machst du eine Methode zur Klassenmethode, d.h. zu brauchst keine Instanz, um die Methode einsetzen zu können.

Ähnlich funktioniert der decorator @classmethod. Mehr dazu findest du in der Doku.

Die eingebaute Funktion any() wird auf eine Sequenz angewendet und liefert True, wenn irgendein Element der Sequenz True ist, sonst False.

Und die Sache mit den "eckigen Klammern" nennt sich list comprehension.
Braucht man nicht unbedingt, ist aber eine nette Sache. Such doch mal danach im Forum.
Crazed
User
Beiträge: 171
Registriert: Sonntag 18. Mai 2008, 11:44

Mittwoch 6. August 2008, 20:24

Vielen Dank für die gründliche und verständliche Antwort numerix.

Zu property und staticmethod.

Wenn property eine Funktion ist und man sie mittels @ benutzen kann (als Dekorator) dann müsste staticmethod genaugenommen doch auch eine build-in function sein, oder?

Code: Alles auswählen

bgcolor = property(getbgcolor, setbgcolor)
Das heißt property gibt eine Variable zurück von der 2 magische Methoden bereits "gehooked" sind. Ich habe keine Ahnung welche aber einmal die die bei Abfrage des Wertes aufgerufen wird (getbgcolor) und die die beim zuweisen aufgerufen wird (setbgcolor), richtig?

Das heißt es kommt ein modifiziertes Variablen Objekt herraus das __get__ und __set__ (oder wie immer sie auch heißen) verändert hat.

Ich hoffe ich habe das richtig verstanden.

Zur List comprehension:

Code: Alles auswählen

    def _get_links(self, types):
        soup = BeautifulSoup.BeautifulSoup(self.browser.open(self.url))
        links = [link.url for link in self.browser.links()]
        links.extend(img['src'] for img in soup('img'))
        return self._filter_links(links, types)
   
    @staticmethod
    def _filter_links(links, types):
        return set(link for link in links if any(link.endswith(t) for t in types))
(Codesnippet aus einem anderen Thread)

Hier wird sogar unten das ohne die [] gemacht sondern () benutzt, das scheint auch möglich zu sein?

MfG,
CracKPod
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Mittwoch 6. August 2008, 20:53

Code: Alles auswählen

class X:
    @staticmethod
    def f(): pass
ist das gleiche wie

Code: Alles auswählen

class X:
    def f(): pass
    f = staticmethod(f)
Ein Decorator wendet nur eine Funktion auf eine grade neu definierte an und bindet den Namen dieser an das, was dabei herauskommt. Sehr interessante Art und Weise, bestimmte Dinge zu machen, die durch Dekoratoren auch arg an Beliebtheit zugenommen hat.

Durch staticmethod und classmethod kann man Funktionen definieren, die entweder statt self kein oder (bei classmethod) die klasse als erstes argument bekommen, damit kannst du Funktionen erstellen, die nicht direkt was mit dem Objekt sondern eher mit der Klasse zu tun haben usw.

property: ich kenn mich damit (und mit new style klassen zeug generell) nicht aus, aber ich habs insoweit auch so verstanden (die methoden heißen aber __getattribute__ und __setattribute__ ;) )

Die Listcomprehension mit ( ) ist eine Generator Expression, macht das gleiche, gibt aber einen Generator zurück statt einer Liste.
lunar

Donnerstag 7. August 2008, 08:56

numerix hat geschrieben:property ist eigentlich kein decorator, sondern eine build-in-function.
Jeder Dekorator ist auch eine Funktion, insofern ist diese Aussage ein bisschen unsinnig.
@staticmethod ist ein decorator.
Und auch eine Funktion ...
Damit machst du eine Methode zur Klassenmethode, d.h. zu brauchst keine Instanz, um die Methode einsetzen zu können.
"staticmethod" erzeugt eine statische Methode, keine Klassenmethode. Der Unterschied besteht darin, dass man innerhalb einer statischen Methode nicht "direkt" auf die Attribute der Klasse zugreifen kann.
Ähnlich funktioniert der decorator @classmethod.
Dieser Dekorator erzeugt nun tatsächlich eine Klassenmethode, weil durch die explizite Übergabe des Klassenobjekts der direkte Zugriff auf die Attribute desselben innerhalb der Methode möglich ist.
DasIch
User
Beiträge: 2465
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Donnerstag 7. August 2008, 11:44

numerix hat geschrieben:Die eingebaute Funktion any() wird auf eine Sequenz angewendet und liefert True, wenn irgendein Element der Sequenz True ist, sonst False.
Generatoren gehen auch oder zählen die mit zu Sequenzen?
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Donnerstag 7. August 2008, 12:24

Alles, über das man iterieren kann.

Code: Alles auswählen

i = iter(foo)
i.next()
Das muss funktionieren.
BlackJack

Donnerstag 7. August 2008, 12:49

In solchen Fällen könnte man auch einfach mal schnell nach Dokumentation schauen, das hilft manchmal ungemein:

Code: Alles auswählen

In [3]: any?
Type:           builtin_function_or_method
Base Class:     <type 'builtin_function_or_method'>
String Form:    <built-in function any>
Namespace:      Python builtin
Docstring:
    any(iterable) -> bool

    Return True if bool(x) is True for any x in the iterable.
Wer kein IPython verwendet, benutzt die `help()`-Funktion statt des Fragezeichens.
lunar

Donnerstag 7. August 2008, 13:04

Oder auch einfach "pydoc any" in der Shell, für alle die Linux nutzen.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Donnerstag 7. August 2008, 14:33

lunar hat geschrieben:
numerix hat geschrieben:property ist eigentlich kein decorator, sondern eine build-in-function.
Jeder Dekorator ist auch eine Funktion, insofern ist diese Aussage ein bisschen unsinnig.
Ja, da hast du Recht. Lag einfach daran, dass es - als ich zu Python kam (was noch nicht so lange her ist) - schon die Dekorator-Notation gab und ich darum nie in die Verlegenheit kam, die Variante

Code: Alles auswählen

f = staticmethod(f)
benutzen zu müssen.

property habe ich dagegen nie in Dekorator-Notation verwendet, was ja auch - wenn ich jetzt nicht falsch denke - nicht besonders sinnvoll wäre:

Code: Alles auswählen

@property
sollte ja das gleiche sein wie

Code: Alles auswählen

f = property(f)
was ja nicht funktionieren dürfte (jedenfalls nicht so, wie man möchte).
lunar hat geschrieben:
Damit machst du eine Methode zur Klassenmethode, d.h. zu brauchst keine Instanz, um die Methode einsetzen zu können.
"staticmethod" erzeugt eine statische Methode, keine Klassenmethode. Der Unterschied besteht darin, dass man innerhalb einer statischen Methode nicht "direkt" auf die Attribute der Klasse zugreifen kann.
Ähnlich funktioniert der decorator @classmethod.
Dieser Dekorator erzeugt nun tatsächlich eine Klassenmethode, weil durch die explizite Übergabe des Klassenobjekts der direkte Zugriff auf die Attribute desselben innerhalb der Methode möglich ist.
Ja, stimmt natürlich auch - das hat BlackJack mir mal in einem schon etwas länger zurückliegenden Thread ausführlich erklärt. :)

Auf dem Stand, auf dem sich die Fragen von Crazed bewegten, schien mir das an dieser Stelle ausreichend. Dazu kommt noch, dass nicht selten im OOP-Sprachgebrauch "Klassenmethode" und "statische Methode" synonym verwendet werden.
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Donnerstag 7. August 2008, 14:43

numerix hat geschrieben:property habe ich dagegen nie in Dekorator-Notation verwendet, was ja auch - wenn ich jetzt nicht falsch denke - nicht besonders sinnvoll wäre:

Code: Alles auswählen

@property
sollte ja das gleiche sein wie

Code: Alles auswählen

f = property(f)
was ja nicht funktionieren dürfte (jedenfalls nicht so, wie man möchte).
Warum nicht? Das wäre ein Attribut, das man nur abfragen, nicht aber setzen kann.
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Donnerstag 7. August 2008, 15:50

Trundle hat geschrieben:
numerix hat geschrieben:property habe ich dagegen nie in Dekorator-Notation verwendet, was ja auch - wenn ich jetzt nicht falsch denke - nicht besonders sinnvoll wäre:

Code: Alles auswählen

@property
sollte ja das gleiche sein wie

Code: Alles auswählen

f = property(f)
was ja nicht funktionieren dürfte (jedenfalls nicht so, wie man möchte).
Warum nicht? Das wäre ein Attribut, das man nur abfragen, nicht aber setzen kann.
Ja, ja, aber danach ist f auch nicht mehr callable, weil das (vorherige) Methodenattribut f durch das (Pseudo)Datenattribut f überschattet wird.
Ob das gewollt ist?

Und: Wie sieht denn der Einsatz von properties mit @-Notation aus?
Das habe ich nicht hinbekommen.
DasIch
User
Beiträge: 2465
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Donnerstag 7. August 2008, 15:57

numerix hat geschrieben:Ja, ja, aber danach ist f auch nicht mehr callable, weil das (vorherige) Methodenattribut f durch das (Pseudo)Datenattribut f überschattet wird.
Ob das gewollt ist?
Wenn man das macht, wird das vermutlich gewollt sein.
Und: Wie sieht denn der Einsatz von properties mit @-Notation aus?

Code: Alles auswählen

@property
def f(*args, **kwargs):
    pass
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

Donnerstag 7. August 2008, 15:58

numerix hat geschrieben:Und: Wie sieht denn der Einsatz von properties mit @-Notation aus?
Das habe ich nicht hinbekommen.

Code: Alles auswählen

class Spam():
    @property
    def eggs(self):
        """Ich bin ein property und das ist mein Docstring und ich gebe
        meinen Namen zurück und hänge Eggs daran."""
        return self.__class__.__name__ + 'Eggs'

print Spam().eggs
Das ist jetzt natürlich ein recht sinnbefreites Beispiel, aber so vom Prinzip.
"Der Dumme erwartet viel. Der Denkende sagt wenig." ("Herr Keuner" -- Bertolt Brecht)
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Mittwoch 13. August 2008, 12:07

Crazed hat geschrieben:Ich habe (leider) erst letztens von den Funktions Dekoratoren gehört. Eine Frage vorweg wie lange gibt es die schon?
Seit Python 2.4.


Die Verwendung von `property` als Decorator ist bei SQLAlchemy (und möglicherweise auch bei SQLObject, aber davon bin ich schon einige Zeit ab) sehr gängig, um Methoden als Felder zu verkleiden (hier als einfaches Beispiel mit dem declarative-Layer):

Code: Alles auswählen

class User(Base):

    id = Column(Integer, primary_key=True)
    first_name = Column(Unicode(40))
    last_name = Column(Unicode(40))

    @property
    def full_name(self):
        return u%s %s' % (self.first_name, self.last_name)
Antworten