variable - python3 static method




Bedeutung von @ classmethod und @ staticmethod für Anfänger? (8)

Bedeutung von @classmethod und @staticmethod ?

  • Eine Methode ist eine Funktion im Namespace eines Objekts, auf die als Attribut zugegriffen werden kann.
  • Eine reguläre (dh Instanz-) Methode ruft die Instanz (wir nennen sie normalerweise self ) als implizites erstes Argument ab.
  • Eine Klassenmethode ruft die Klasse (wir nennen sie normalerweise cls ) als implizites erstes Argument ab.
  • Eine statische Methode erhält kein implizites erstes Argument (wie eine reguläre Funktion).

Wann sollte ich sie verwenden, warum sollte ich sie verwenden und wie sollte ich sie verwenden?

Sie brauchen keinen Dekorateur. Aber nach dem Prinzip, dass Sie die Anzahl der Argumente für Funktionen minimieren sollten (siehe Clean Coder), sind sie nützlich, um genau das zu tun.

class Example(object):

    def regular_instance_method(self):
        """A function of an instance has access to every attribute of that 
        instance, including its class (and its attributes.)
        Not accepting at least one argument is a TypeError.
        Not understanding the semantics of that argument is a user error.
        """
        return some_function_f(self)

    @classmethod
    def a_class_method(cls):
        """A function of a class has access to every attribute of the class.
        Not accepting at least one argument is a TypeError.
        Not understanding the semantics of that argument is a user error.
        """
        return some_function_g(cls)

    @staticmethod
    def a_static_method():
        """A static method has no information about instances or classes
        unless explicitly given. It just lives in the class (and thus its 
        instances') namespace.
        """
        return some_function_h()

Für beide Instanzmethoden und Klassenmethoden akzeptiert kein TypeError mindestens ein Argument, aber die Semantik dieses Arguments ist kein Benutzerfehler.

(Definieren Sie some_function , zB:

some_function_h = some_function_g = some_function_f = lambda x=None: x

und das wird funktionieren.)

Gepunktetes Suchen nach Instanzen und Klassen:

Eine gepunktete Suche auf einer Instanz wird in dieser Reihenfolge durchgeführt - wir suchen nach:

  1. ein Datendeskriptor im Klassennamespace (wie eine Eigenschaft)
  2. Daten in der Instanz __dict__
  3. ein Nicht-Datendeskriptor im Klassennamespace (Methoden).

Beachten Sie, dass eine punktierte Suche in einer Instanz wie folgt aufgerufen wird:

instance = Example()
instance.regular_instance_method 

und Methoden sind aufrufbare Attribute:

instance.regular_instance_method()

Instanzmethoden

Das Argument self wird implizit durch die punktierte Suche angegeben.

Sie müssen auf Instanzmethoden von Instanzen der Klasse zugreifen.

>>> instance = Example()
>>> instance.regular_instance_method()
<__main__.Example object at 0x00000000399524E0>

Klassenmethoden

Das Argument, cls , wird implizit über das punktierte Nachschlagen gegeben.

Sie können auf diese Methode über eine Instanz oder die Klasse (oder Unterklassen) zugreifen.

>>> instance.a_class_method()
<class '__main__.Example'>
>>> Example.a_class_method()
<class '__main__.Example'>

statische Methoden

Implizit sind keine Argumente angegeben. Diese Methode funktioniert wie jede Funktion, die zum Beispiel im Namespace eines Moduls definiert ist, außer dass sie nachgeschlagen werden kann

>>> print(instance.a_static_method())
None

Wann sollte ich sie wieder benutzen, warum sollte ich sie benutzen?

Jeder von ihnen ist in den Informationen, die er die Methode Methode gegen Instanz übergeben, zunehmend restriktiver.

Verwenden Sie sie, wenn Sie die Informationen nicht benötigen.

Dies erleichtert es Ihnen, Ihre Funktionen und Methoden zu analysieren und zu testen.

Was ist einfacher zu verstehen?

def function(x, y, z): ...

oder

def function(y, z): ...

oder

def function(z): ...

Die Funktionen mit weniger Argumenten sind einfacher zu verstehen. Sie sind auch leichter zu testen.

Diese ähneln Instanz-, Klassen- und statischen Methoden. Denken Sie daran, dass, wenn wir eine Instanz haben, wir auch ihre Klasse haben, fragen Sie sich erneut, worüber man leichter nachdenken kann:

def an_instance_method(self, arg, kwarg=None):
    cls = type(self)             # Also has the class of instance!
    ...

@classmethod
def a_class_method(cls, arg, kwarg=None):
    ...

@staticmethod
def a_static_method(arg, kwarg=None):
    ...

Eingebaute Beispiele

Hier sind ein paar meiner Lieblingsbeispiele:

Die statische Methode str.maketrans war eine Funktion im string Modul, aber es ist viel bequemer, dass sie vom str Namespace aus zugänglich ist.

>>> 'abc'.translate(str.maketrans({'a': 'b'}))
'bbc'

Die dict.fromkeys Klassenmethode gibt ein neues Wörterbuch aus, das aus einem iterierbaren Schlüssel instanziiert wurde:

>>> dict.fromkeys('abc')
{'a': None, 'c': None, 'b': None}

Bei Unterklassen sehen wir, dass es die Klasseninformationen als eine Klassenmethode erhält, was sehr nützlich ist:

>>> class MyDict(dict): pass
>>> type(MyDict.fromkeys('abc'))
<class '__main__.MyDict'> 

Mein Rat - Schlussfolgerung

Verwenden Sie statische Methoden, wenn Sie die Klassen- oder Instanzargumente nicht benötigen, die Funktion jedoch mit der Verwendung des Objekts verknüpft ist und die Funktion sich im Namespace des Objekts befindet.

Verwenden Sie Klassenmethoden, wenn Sie keine Instanzinformationen benötigen, aber die Klasseninformationen vielleicht für ihre anderen Klassen- oder statischen Methoden oder vielleicht selbst als Konstruktor benötigen. (Sie würden die Klasse nicht hart codieren, so dass Unterklassen hier verwendet werden könnten.)

Könnte mir jemand die Bedeutung von @classmethod und @staticmethod in Python erklären? Ich muss den Unterschied und die Bedeutung wissen.

Soweit ich verstehe, teilt @classmethod einer Klasse mit, dass es sich um eine Methode handelt, die in Unterklassen oder ... etwas vererbt werden soll. Worum geht es jedoch? Warum nicht einfach die Klassenmethode definieren, ohne @classmethod oder @staticmethod oder irgendwelche @ Definitionen hinzuzufügen?

tl; dr: Wann sollte ich sie benutzen, warum sollte ich sie benutzen und wie sollte ich sie benutzen?

Ich bin ziemlich fortgeschritten mit C ++, daher sollte die Verwendung fortgeschrittener Programmierkonzepte kein Problem sein. Fühlen Sie sich frei, geben Sie mir ein entsprechendes C ++ - Beispiel, wenn möglich.


Die Klassenmethode kann den Klassenstatus ändern, sie an die Klasse gebunden und cls als Parameter enthalten.

Die statische Methode kann den Klassenstatus nicht ändern, sie ist an die Klasse gebunden und kennt Klasse oder Instanz nicht

class empDetails:
    def __init__(self,name,sal):
        self.name=name
        self.sal=sal
    @classmethod
    def increment(cls,name,none):
        return cls('yarramsetti',6000 + 500)
    @staticmethod
    def salChecking(sal):
        return sal > 6000

emp1=empDetails('durga prasad',6000)
emp2=empDetails.increment('yarramsetti',100)
# output is 'durga prasad'
print emp1.name
# output put is 6000
print emp1.sal
# output is 6500,because it change the sal variable
print emp2.sal
# output is 'yarramsetti' it change the state of name variable
print emp2.name
# output is True, because ,it change the state of sal variable
print empDetails.salChecking(6500)

Ich bin ein Anfänger auf dieser Seite, ich habe alle obigen Antworten gelesen, und habe die Information bekommen, was ich will. Ich habe jedoch kein Recht auf Verbesserung. Also möchte ich mit der Antwort starten, so wie ich es verstehe.

  • @staticmethod benötigt weder self noch cls als ersten Parameter der Methode
  • @staticmethod und @classmethod function können von @classmethod oder Klassenvariablen aufgerufen werden
  • @staticmethod dekorierte Funktion hat Auswirkungen auf eine Art "unveränderbare Eigenschaft", die diese Unterklassenvererbung nicht überschreiben kann, da ihre Basisklassenfunktion von einem @staticmethod Dekorator @staticmethod .
  • @classmethod benötigt cls ( @classmethod , Sie können den Variablennamen ändern, wenn Sie möchten, aber es wird nicht empfohlen) als erster Parameter der Funktion
  • @classmethod immer von der Unterklassenart verwendet, die Unterklassenvererbung kann den Effekt der Basisklassenfunktion ändern, dh @classmethod Basisklassenfunktion könnte von verschiedenen Unterklassen überschrieben werden.

Ich habe versucht, ein einfaches Beispiel zu schreiben, um den Unterschied zwischen der Verwendung von staticmethod und classmethod zu zeigen (und sie auch nicht zu verwenden). Hier ist der Code:

#without decorator:
class Duck(object):
    def sound(self):
        print("Quack")


#pay attention to the "sound" function:

#with @staticmethod
class Cat(object):
    @staticmethod
    def sound():
        print("Meow")

#with @classmethod
class Dog(object):
    @classmethod
    def sound(self):
        print("woof")


#notice the differences between calling them:
Duck().sound()
Cat.sound()
Dog.sound()

#prints:
"""
Quack
Meow
woof
"""

Man würde @classmethod wenn er das Verhalten der Methode ändern möchte, basierend darauf, welche Unterklasse die Methode aufruft. Denken Sie daran, dass wir in einer Klassenmethode einen Verweis auf die aufrufende Klasse haben.

Wenn Sie static verwenden, möchten Sie, dass das Verhalten in den Unterklassen unverändert bleibt

Beispiel:

class Hero:

  @staticmethod
  def say_hello():
     print("Helllo...")

  @classmethod
  def say_class_hello(cls):
     if(cls.__name__=="HeroSon"):
        print("Hi Kido")
     elif(cls.__name__=="HeroDaughter"):
        print("Hi Princess")

class HeroSon(Hero):
  def say_son_hello(self):
     print("test  hello")



class HeroDaughter(Hero):
  def say_daughter_hello(self):
     print("test  hello daughter")


testson = HeroSon()

testson.say_class_hello() #Output: "Hi Kido"

testson.say_hello() #Outputs: "Helllo..."

testdaughter = HeroDaughter()

testdaughter.say_class_hello() #Outputs: "Hi Princess"

testdaughter.say_hello() #Outputs: "Helllo..."

Obwohl die classmethod und die staticmethod sehr ähnlich sind, gibt es einen kleinen Unterschied in der Verwendung beider Entitäten: Die classmethod muss einen Verweis auf ein Klassenobjekt als ersten Parameter haben, während staticmethod überhaupt keine Parameter haben darf.

Beispiel

class Date(object):

    def __init__(self, day=0, month=0, year=0):
        self.day = day
        self.month = month
        self.year = year

    @classmethod
    def from_string(cls, date_as_string):
        day, month, year = map(int, date_as_string.split('-'))
        date1 = cls(day, month, year)
        return date1

    @staticmethod
    def is_date_valid(date_as_string):
        day, month, year = map(int, date_as_string.split('-'))
        return day <= 31 and month <= 12 and year <= 3999

date2 = Date.from_string('11-09-2012')
is_date = Date.is_date_valid('11-09-2012')

Erläuterung

Nehmen wir ein Beispiel für eine Klasse an, die sich mit Datumsinformationen befasst (das ist unser Standardbaustein zum Kochen):

class Date(object):

    def __init__(self, day=0, month=0, year=0):
        self.day = day
        self.month = month
        self.year = year

Diese Klasse könnte natürlich verwendet werden, um Informationen über bestimmte Daten zu speichern (ohne Zeitzoneninformationen; angenommen, alle Daten sind in UTC dargestellt).

Hier haben wir __init__ , einen typischen Initialisierer von Python-Klasseninstanzen, der Argumente als eine typische instancemethod empfängt, die das erste nicht optionale Argument ( self ) enthält, das auf eine neu erstellte Instanz verweist.

Klassenmethode

Wir haben einige Aufgaben, die mit classmethod gut erledigt werden classmethod .

Nehmen wir an, dass wir eine Vielzahl von Instanzen der Date Klasse erstellen möchten, deren Datumsinformationen von der äußeren Quelle stammen, die als Zeichenfolge des nächsten Formats codiert ist ('TT-MM-JJJJ'). Das müssen wir an verschiedenen Stellen unseres Quellcodes im Projekt tun.

Was wir hier tun müssen, ist:

  1. Analysiere eine Zeichenkette, um Tag, Monat und Jahr als drei ganzzahlige Variablen oder ein 3-Punkte-Tupel, bestehend aus dieser Variablen, zu erhalten.
  2. Instanziieren Sie das Date indem Sie diese Werte an den Initialisierungsaufruf übergeben.

Das wird so aussehen:

day, month, year = map(int, string_date.split('-'))
date1 = Date(day, month, year)

Zu diesem Zweck hat C ++ eine Funktion wie Überladen, aber Python fehlt diese Funktion - also hier, wenn die classmethod zutrifft. Lass uns einen anderen " Konstruktor " erstellen.

    @classmethod
    def from_string(cls, date_as_string):
        day, month, year = map(int, date_as_string.split('-'))
        date1 = cls(day, month, year)
        return date1

date2 = Date.from_string('11-09-2012')

Sehen wir uns die obige Implementierung genauer an und überprüfen Sie, welche Vorteile wir hier haben:

  1. Wir haben das Parsen von Datumsstrings an einer Stelle implementiert und es ist jetzt wiederverwendbar.
  2. Encapsulation funktioniert hier gut (wenn Sie denken, dass Sie String-Parsing als eine einzige Funktion an anderer Stelle implementieren könnten, passt diese Lösung besser zum OOP-Paradigma).
  3. cls ist ein Objekt, das die Klasse selbst und nicht eine Instanz der Klasse enthält. Es ist ziemlich cool, denn wenn wir unsere Date Klasse erben, wird auch für alle Kinder from_string definiert.

Statische Methode

Was ist mit der staticmethod ? Es ist der classmethod ähnlich, classmethod aber keine obligatorischen Parameter (wie eine Klassenmethode oder Instanzmethode).

Sehen wir uns den nächsten Anwendungsfall an.

Wir haben eine Datumsangabe, die wir irgendwie validieren wollen. Diese Aufgabe ist auch logisch an die Date Klasse gebunden, die wir bisher verwendet haben, erfordert aber immer noch keine Instanziierung.

Hier kann staticmethod nützlich sein. Schauen wir uns das nächste Stück Code an:

    @staticmethod
    def is_date_valid(date_as_string):
        day, month, year = map(int, date_as_string.split('-'))
        return day <= 31 and month <= 12 and year <= 3999

    # usage:
    is_date = Date.is_date_valid('11-09-2012')

Wie wir aus der Verwendung der staticmethod , haben wir keinen Zugriff darauf, was die Klasse ist - es ist im Grunde nur eine Funktion, syntaktisch wie eine Methode, aber ohne Zugriff auf das Objekt und seine Interna (Felder und andere Methoden) ), während das classmethod tut.


@classmethod bedeutet: Wenn diese Methode aufgerufen wird, übergeben wir die Klasse als erstes Argument anstelle der Instanz dieser Klasse (wie wir es normalerweise mit Methoden tun). Dies bedeutet, dass Sie die Klasse und ihre Eigenschaften innerhalb dieser Methode anstelle einer bestimmten Instanz verwenden können.

@staticmethod bedeutet: Wenn diese Methode aufgerufen wird, übergeben wir keine Instanz der Klasse (wie normalerweise bei Methoden). Dies bedeutet, dass Sie eine Funktion in eine Klasse einfügen können, aber nicht auf die Instanz dieser Klasse zugreifen können (dies ist nützlich, wenn Ihre Methode die Instanz nicht verwendet).


@staticmethod Funktion ist nichts anderes als eine Funktion, die in einer Klasse definiert ist. Es kann aufgerufen werden, ohne zuerst die Klasse zu instanziieren. Die Definition ist durch Vererbung unveränderbar.

  • Python muss keine gebundene Methode für ein Objekt instanziieren.
  • Es erleichtert die Lesbarkeit des Codes: Da wir @staticmethod sehen , wissen wir, dass die Methode nicht vom Zustand des Objekts selbst abhängt.

@classmethod Funktion auch aufrufbar, ohne die Klasse zu instanziieren, aber ihre Definition folgt Sub-Klasse, nicht Parent-Klasse, über Vererbung, kann durch Unterklasse überschrieben werden. Das liegt daran, dass das erste Argument für @classmethod Funktion @classmethod immer cls (class) .

  • Factory-Methoden , die verwendet werden, um eine Instanz für eine Klasse zu erstellen, die beispielsweise eine Art von Vorverarbeitung verwendet.
  • Statische Methoden, die statische Methoden aufrufen : Wenn Sie statische Methoden in mehrere statische Methoden aufteilen, sollten Sie den Klassennamen nicht fest codieren, sondern Klassenmethoden verwenden

here ist ein guter Link zu diesem Thema.





class-method