Seite 1 von 1

Wozu braucht man @classmethod überhaupt?

Verfasst: Freitag 15. Juni 2018, 14:37
von TheGrudge
Hi,

die meisten fragen ja immer, was der Sinn von @staticmethod eigentlich ist, da diese ja weder die Instanz noch die Klasse als Parameter übergeben bekommen.
Ich frage mich nur gerade, wozu man @classmethod braucht, da ich doch alles auch mit @staticmethod realisieren kann.

Als Anwendungsbeispiel für @classmethod werden gerne alternative Konstruktoren (bzw Factorymethoden genannt). Aber diese sind doch auch mit @staticmethod realisierbar.
Zum Beispiel:

Code: Alles auswählen

class Person:
    num = 0

    def __init__(self, firstname, lastname):
        self.firstname = firstname
        self.lastname = lastname

    def __repr__(self):
        return f'{self.firstname} {self.lastname} (#{self.num})'

    @classmethod
    def create(cls):
        cls.num += 1
        return cls('John', 'Doe')

    @staticmethod
    def create2():
        Person.num += 1
        return Person('John', 'Doe')


def main():
    p = Person.create()
    print(p)

    p2 = Person.create2()
    print(p2)


if __name__ == '__main__':
    main()
Beide create-Funktionen erstellen ein neues Person-Objekt und zählen die Klassenvariable "num" hoch. Vom Verhalten her gibt es wohl keinen Unterschied.
Haben @classmethod gegenüber @staticmethod irgendwelche Vorteile, oder sind das letztendlich nur Konventionen, damit man sieht, welchen "Scope" diese Methoden haben.

Gerade für Menschen, die aus Sprachen wie Java oder C# kommen, ist dieses Konzept verwirrend, denn eigentlich sind @classmethod ja eher gleichzusetzen mit statischen Methoden in Java und C# als @staticmethod.
Übersehe ich was?
Bringen @classmethod Definitionen irgendwelche Vorteile zu @staticmethod Definitionen?
Vielleicht im Speicherverbrauch oder Geschwindigkeit?

Dazu habe ich leider noch keine genauere Beschreibung gefunden.

Re: Wozu braucht man @classmethod überhaupt?

Verfasst: Freitag 15. Juni 2018, 15:26
von DasIch
Vererbung.

Re: Wozu braucht man @classmethod überhaupt?

Verfasst: Freitag 15. Juni 2018, 15:42
von __blackjack__
@TheGrudge: Den Unterschied siehst Du doch an der Signatur der Klassenmethode: Du bekommst da die Klasse auf der das aufgerufen wurde. Nicht die in der es definiert wurde! `classmethod()` gibt's in Java nicht, und in C# AFAIK auch nicht. Die statischen Methoden in Java sind mit `staticmethod()` vergleichbar.

Zu den Vorteilen: @classmethod/@staticmethod dokumentieren zum Beispiel das der Aufruf nichts am Objekt ändern kann. Und im Falle von @classmethod, das sie eigentlich bevorzugt auf der Klasse aufgerufen werden sollte. Und bei @staticmethod dient das auch als Dokumentation das man diese Funktion absichtlich in die Klasse gesteckt hat und weiss was man da tut. Denn bei einer ”Methode” die `self` nicht verwendet, stellt sich ja auch immer die Frage was die dann in der Klasse zu suchen hat und warum sie nicht einfach eine Funktion auf Modulebene ist.

Re: Wozu braucht man @classmethod überhaupt?

Verfasst: Freitag 15. Juni 2018, 16:20
von __deets__
@TheGrudge: die Klasse, die du bekommst in der class-method ist die Klasse auf der deine Factory-Methode *aufgerufen* wurde. Womit du zB problemlos eine Ableitung von Person einfuehren kannst, und die immer noch mit der "alten" Factory-Methode erzeugen.

Code: Alles auswählen

class Person(...):
      ...
      @classmethod
      def create(cls, *a, **k):
             person = cls(*a, **k)
             ZENTRALREGISTER.melde_an(person)
             return person

class PersonaNonGrata(Person):
         ...

ich = PersonaNonGrata.create("peter", "pasulke")

Re: Wozu braucht man @classmethod überhaupt?

Verfasst: Sonntag 17. Juni 2018, 14:07
von TheGrudge
ah ok ja jetzt macht der Unterschied Sinn :-)
Danke für eure Antworten.