Wozu braucht man @classmethod überhaupt?

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
TheGrudge
User
Beiträge: 96
Registriert: Donnerstag 4. Mai 2006, 18:39

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

Vererbung.
Benutzeravatar
__blackjack__
User
Beiträge: 13071
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@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.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
__deets__
User
Beiträge: 14523
Registriert: Mittwoch 14. Oktober 2015, 14:29

@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")
Benutzeravatar
TheGrudge
User
Beiträge: 96
Registriert: Donnerstag 4. Mai 2006, 18:39

ah ok ja jetzt macht der Unterschied Sinn :-)
Danke für eure Antworten.
Antworten