Seite 1 von 1

Class Methods

Verfasst: Samstag 3. März 2007, 18:20
von veers
Hi ihrs,

Etwas das ich an Python bisher noch nicht verstanden habe ist wie ich "Klassen Methoden" definieren kann. So etwas in der Art:

Code: Alles auswählen

class Foo(object):
    def Bar():
        print "Foobar"
Foo.Bar()
Das Funktionier jedoch nicht:

Code: Alles auswählen

TypeError: unbound method Bar() must be called with Foo instance as first argument (got nothing instead)
Ist das in Python überhaupt möglich? Wenn ja, wie?

Verfasst: Samstag 3. März 2007, 18:52
von BlackJack
Das was Du möchtest heisst in Python `staticmethod`:

Code: Alles auswählen

class Spam:
    @staticmethod
    feep():
        pass
Klassenmethoden gibt's auch (`classmethod`), die bekommen als erstes Argument "automagisch" die Klasse übergeben anstatt der Instanz wie bei normalen Methoden.

Verfasst: Samstag 3. März 2007, 19:29
von veers
Vielen dank, war genau was ich gesucht habe.

Verfasst: Samstag 3. März 2007, 19:33
von Ene Uran
Normalerweise wird eine Klasse so zusammengebastelt:

Code: Alles auswählen

class Foo(object):
    # this is the class constructor
    def __init__(self):
        pass
    
    def Bar(self):
        print "Foobar"

# instance of class
foo1 = Foo()
foo1.Bar()   # --> Foobar
# oder ...
Foo().Bar()  # --> Foobar
Die Instanz gibt der Klasse Macht!

Bist Du wirklich faul, dann gehts auch so:

Code: Alles auswählen

class Foo(object):
    @staticmethod
    def Bar():
        print "Foobar"
        
Foo.Bar()  # --> Foobar

Verfasst: Samstag 3. März 2007, 20:36
von BlackJack
Das hat nicht zwingend was mit "faul" zu tun. Es macht zum Beispiel Sinn Factory-Funktionen, die Objekte vom Typ der Klasse liefern, als `staticmethod` oder `classmethod` an die Klasse zu binden.

Verfasst: Sonntag 4. März 2007, 17:17
von sape
@Ene Uran: Staticmethoden != "Instanzmethoden".

Ein Instanzmethode kann nur über die Instanz der Klasse benutzt werden.
``Foo().Bar()`` <- ``Foo()'' (Man achte auf die Klammern) erzeugt ein Objekt (Instanz) der Klasse ``Foo``. ``.Bar()`` ruft die "Instanzmethoden" für die eben erzeugt Instanz auf.

``Foo.Bar()`` <- Ruft die Staticmethoden der Klasse ``Foo`` auf.

Das schöne an statischen Methoden ist, das man eine Klasse als Namencpace benutzen kann (Die *nicht* zur instanziierung gedacht ist!) um zusammengehöriges in besagten zu kapseln. Bei Attributen ist das trivial, da man sie als Klassenattribute definiert:

Code: Alles auswählen

class Foo(object):
    attr1 = None
    attr2 = None
print Foo.attr1
Bei Methoden wird es unschön wenn sie als Instanzmethoden defineirt werden, da man immer erst eine Instanz bilden muss um die Methode aufzurufen: In anderen Worten: Ich muss vor dem Klassennamen eine öffnenden und schließenden Klammer schreiben:

Code: Alles auswählen

class Foo(object):
    attr1 = None
    attr2 = None
    def Bar(self):
        pass
print Foo.attr1
Foo().Bar() # :-[
Hier kommt nun ``@staticmethod`` ins spiel mit dem es nicht notwendig ist die klasse zu instanziieren:

Code: Alles auswählen

class Foo(object):
    attr1 = None
    attr2 = None

    @staticmethod
    def Bar(self):
        pass
print Foo.attr1
Foo.Bar() # :-)
Ich nutze das Feature gelegentlich für Objekte die ein Namenspace, und nicht mehr, sein sollen, in dem Konstanten und statische Methoden als Modifikatoren definiert sind, um alles unter einem Namen zusammenzufassen. So muss ich nicht extra ein Module schreiben um zusammengehöriges in einem Namensraum zusammenzufassen, sondern es langt einfach eine Klasse dafür :)