Was ist der Zweck von Klassenmethoden?

250

Ich bringe mir Python bei und meine letzte Lektion war, dass Python kein Java ist. Deshalb habe ich nur eine Weile damit verbracht, alle meine Klassenmethoden in Funktionen umzuwandeln.

Mir ist jetzt klar, dass ich für das, was ich mit staticMethoden in Java machen würde, keine Klassenmethoden verwenden muss , aber jetzt bin ich mir nicht sicher, wann ich sie verwenden würde. Alle Ratschläge, die ich zu Python Class-Methoden finden kann, beziehen sich auf Neulinge, wie ich sie meiden sollte, und die Standarddokumentation ist bei der Diskussion am undurchsichtigsten.

Hat jemand ein gutes Beispiel für die Verwendung einer Klassenmethode in Python oder kann mir zumindest jemand sagen, wann Klassenmethoden sinnvoll eingesetzt werden können?

Dave Webb
quelle

Antworten:

178

Klassenmethoden sind für den Fall gedacht, dass Sie Methoden benötigen, die nicht spezifisch für eine bestimmte Instanz sind, die Klasse jedoch in irgendeiner Weise einbeziehen. Das Interessanteste an ihnen ist, dass sie von Unterklassen überschrieben werden können, was mit den statischen Methoden von Java oder den Funktionen auf Modulebene von Python einfach nicht möglich ist.

Wenn Sie eine Klasse MyClassund eine Funktion auf Modulebene haben, die auf MyClass ausgeführt wird (Factory, Dependency Injection Stub usw.), machen Sie es zu einer classmethod. Dann steht es Unterklassen zur Verfügung.

John Millikin
quelle
Aha. Aber wie wäre es, wenn ich nur eine Methode kategorisieren möchte, die MyClass nicht benötigt, aber dennoch irgendwie sinnvoll ist, wenn ich in einer anderen MyClass gruppiere? Ich kann mir
vorstellen
Ich habe eine Frage zum Original. Vielleicht können Sie sie gleichzeitig beantworten? Welche Art, Klassenmethoden eines Objekts aufzurufen, ist "besser" oder "idiomatischer": obj.cls_mthd(...)oder type(obj).cls_mthd(...)?
Alexey
63

Factory-Methoden (alternative Konstruktoren) sind in der Tat ein klassisches Beispiel für Klassenmethoden.

Grundsätzlich sind Klassenmethoden immer dann geeignet, wenn Sie eine Methode haben möchten, die natürlich in den Namespace der Klasse passt, aber keiner bestimmten Instanz der Klasse zugeordnet ist.

Als Beispiel im hervorragenden Unipath- Modul:

Aktuelles Verzeichnis

  • Path.cwd()
    • Gibt das aktuelle Verzeichnis zurück. zB , Path("/tmp/my_temp_dir"). Dies ist eine Klassenmethode.
  • .chdir()
    • Machen Sie sich das aktuelle Verzeichnis.

Da das aktuelle Verzeichnis prozessweit ist, verfügt die cwdMethode über keine bestimmte Instanz, der sie zugeordnet werden sollte. Ändern Sie jedoch das cwdin das Verzeichnis eines bestimmtenPath Instanz sollte jedoch tatsächlich eine Instanzmethode sein.

Hmmm ... wie Path.cwd()es tatsächlich eine PathInstanz zurückgibt , könnte es als Fabrikmethode angesehen werden ...

Wayne Werner
quelle
1
Ja ... Fabrikmethoden waren das erste, was mir in den Sinn kam. In diesem Sinne gibt es auch Dinge, die ein Singleton-Muster implementieren würden, wie: getAndOptionallyCreateSomeSingleInstanceOfSomeResource ()
Jemenake
3
In Python sind dies statische Methoden, keine Klassenmethoden.
Jaykul
46

Stellen Sie sich das so vor: Normale Methoden sind nützlich, um die Details des Versands auszublenden: Sie können eingeben, myobj.foo()ohne sich Gedanken darüber zu machen, ob die foo()Methode von der myobjKlasse des Objekts oder einer seiner übergeordneten Klassen implementiert wird . Klassenmethoden sind genau analog dazu, aber stattdessen mit dem Klassenobjekt: Sie können aufrufen, MyClass.foo()ohne sich Gedanken darüber machen zu müssen, ob foo()sie speziell von implementiert werden, MyClassweil sie eine eigene spezielle Version benötigen, oder ob die übergeordnete Klasse den Aufruf verarbeiten kann.

Klassenmethoden sind wichtig, wenn Sie eine Einrichtung oder Berechnung durchführen, die der Erstellung einer tatsächlichen Instanz vorausgeht , da Sie die Instanz offensichtlich erst dann als Versandpunkt für Ihre Methodenaufrufe verwenden können, wenn die Instanz vorhanden ist. Ein gutes Beispiel finden Sie im SQLAlchemy-Quellcode. Schauen Sie sich die dbapi()Klassenmethode unter folgendem Link an:

https://github.com/zzzeek/sqlalchemy/blob/ab6946769742602e40fb9ed9dde5f642885d1906/lib/sqlalchemy/dialects/mssql/pymssql.py#L47

Sie können sehen, dass die dbapi()Methode, mit der ein Datenbank-Backend die herstellerspezifische Datenbankbibliothek importiert, die sie bei Bedarf benötigt, eine Klassenmethode ist, da sie ausgeführt werden muss, bevor Instanzen einer bestimmten Datenbankverbindung erstellt werden können. Dies ist jedoch nicht möglich eine einfache oder statische Funktion sein, weil sie möchte, dass sie andere unterstützende Methoden aufrufen kann, die in ähnlicher Weise möglicherweise spezifischer in Unterklassen als in ihrer übergeordneten Klasse geschrieben werden müssen. Und wenn Sie an eine Funktion oder statische Klasse senden, "vergessen" Sie und verlieren das Wissen darüber, welche Klasse die Initialisierung durchführt.

Brandon Rhodes
quelle
Defekter Link, bitte anpassen
piertoni
28

Ich wollte kürzlich eine sehr leichte Protokollierungsklasse, die je nach Protokollierungsstufe, die programmgesteuert festgelegt werden kann, unterschiedliche Ausgabemengen ausgibt. Ich wollte die Klasse jedoch nicht jedes Mal instanziieren, wenn ich eine Debugging-Nachricht, einen Fehler oder eine Warnung ausgeben wollte. Ich wollte aber auch die Funktionsweise dieser Protokollierungsfunktion zusammenfassen und ohne die Deklaration von Globals wiederverwendbar machen.

Also habe ich Klassenvariablen und den @classmethodDekorator verwendet, um dies zu erreichen.

Mit meiner einfachen Protokollierungsklasse könnte ich Folgendes tun:

Logger._level = Logger.DEBUG

Wenn ich dann in meinem Code eine Reihe von Debugging-Informationen ausspucken wollte, musste ich einfach codieren

Logger.debug( "this is some annoying message I only want to see while debugging" )

Fehler könnten ausgegeben werden

Logger.error( "Wow, something really awful happened." )

In der "Produktions" -Umgebung kann ich angeben

Logger._level = Logger.ERROR

und jetzt wird nur die Fehlermeldung ausgegeben. Die Debug-Nachricht wird nicht gedruckt.

Hier ist meine Klasse:

class Logger :
    ''' Handles logging of debugging and error messages. '''

    DEBUG = 5
    INFO  = 4
    WARN  = 3
    ERROR = 2
    FATAL = 1
    _level = DEBUG

    def __init__( self ) :
        Logger._level = Logger.DEBUG

    @classmethod
    def isLevel( cls, level ) :
        return cls._level >= level

    @classmethod
    def debug( cls, message ) :
        if cls.isLevel( Logger.DEBUG ) :
            print "DEBUG:  " + message

    @classmethod
    def info( cls, message ) :
        if cls.isLevel( Logger.INFO ) :
            print "INFO :  " + message

    @classmethod
    def warn( cls, message ) :
        if cls.isLevel( Logger.WARN ) :
            print "WARN :  " + message

    @classmethod
    def error( cls, message ) :
        if cls.isLevel( Logger.ERROR ) :
            print "ERROR:  " + message

    @classmethod
    def fatal( cls, message ) :
        if cls.isLevel( Logger.FATAL ) :
            print "FATAL:  " + message

Und ein Code, der es nur ein bisschen testet:

def logAll() :
    Logger.debug( "This is a Debug message." )
    Logger.info ( "This is a Info  message." )
    Logger.warn ( "This is a Warn  message." )
    Logger.error( "This is a Error message." )
    Logger.fatal( "This is a Fatal message." )

if __name__ == '__main__' :

    print "Should see all DEBUG and higher"
    Logger._level = Logger.DEBUG
    logAll()

    print "Should see all ERROR and higher"
    Logger._level = Logger.ERROR
    logAll()
Marvo
quelle
10
Dies scheint mir kein gutes Beispiel zu sein, für das Klassenmethoden gut sind, da alles auf weniger komplexe Weise hätte erledigt werden können, indem einfach alle Funktionen der Klassenmethoden auf Modulebene ausgeführt und die Klasse insgesamt abgeschafft wurden.
Martineau
10
Noch wichtiger ist, dass Python eine sehr einfach zu verwendende Protokollierungsklasse bietet. Schlimmer als eine weniger als optimale Lösung zu schaffen, habe ich das Rad neu erfunden. Doppelhandschlag. Aber es liefert zumindest ein funktionierendes Beispiel. Ich bin mir nicht sicher, ob ich damit einverstanden bin, die Klasse auf konzeptioneller Ebene loszuwerden. Manchmal möchten Sie Code für eine einfache Wiederverwendung kapseln, und Protokollierungsmethoden sind ein hervorragendes Ziel für die Wiederverwendung.
Marvo
3
Warum würden Sie keine statische Methode verwenden?
Bdforbes
26

Alternative Konstruktoren sind das klassische Beispiel.

Aaron Maenpaa
quelle
10

Wenn sich ein Benutzer auf meiner Website anmeldet, wird ein User () -Objekt aus dem Benutzernamen und dem Kennwort instanziiert.

Wenn ich ein Benutzerobjekt benötige, ohne dass der Benutzer zum Anmelden da ist (z. B. möchte ein Administrator möglicherweise ein anderes Benutzerkonto löschen, daher muss ich diesen Benutzer instanziieren und seine Löschmethode aufrufen):

Ich habe Klassenmethoden, um das Benutzerobjekt zu greifen.

class User():
    #lots of code
    #...
    # more code

    @classmethod
    def get_by_username(cls, username):
        return cls.query(cls.username == username).get()

    @classmethod
    def get_by_auth_id(cls, auth_id):
        return cls.query(cls.auth_id == auth_id).get()
Robert King
quelle
9

Ich denke, die klarste Antwort ist die von AmanKow . Es läuft darauf hinaus, wie Sie Ihren Code organisieren möchten. Sie können alles als Funktionen auf Modulebene schreiben, die in den Namespace des Moduls eingeschlossen sind, d. H.

module.py (file 1)
---------
def f1() : pass
def f2() : pass
def f3() : pass


usage.py (file 2)
--------
from module import *
f1()
f2()
f3()
def f4():pass 
def f5():pass

usage1.py (file 3)
-------------------
from usage import f4,f5
f4()
f5()

Der obige Verfahrenscode ist nicht gut organisiert, da Sie sehen können, dass es nach nur 3 Modulen verwirrend wird. Was macht jede Methode? Sie können lange beschreibende Namen für Funktionen verwenden (wie in Java), aber Ihr Code wird sehr schnell nicht mehr verwaltet.

Die objektorientierte Methode besteht darin, Ihren Code in verwaltbare Blöcke aufzuteilen, dh Klassen und Objekte und Funktionen können Objektinstanzen oder Klassen zugeordnet werden.

Mit Klassenfunktionen erhalten Sie eine andere Unterteilungsebene in Ihrem Code als mit Funktionen auf Modulebene. Sie können also verwandte Funktionen innerhalb einer Klasse gruppieren, um sie spezifischer für eine Aufgabe zu machen, die Sie dieser Klasse zugewiesen haben. Sie können beispielsweise eine Datei-Dienstprogrammklasse erstellen:

class FileUtil ():
  def copy(source,dest):pass
  def move(source,dest):pass
  def copyDir(source,dest):pass
  def moveDir(source,dest):pass

//usage
FileUtil.copy("1.txt","2.txt")
FileUtil.moveDir("dir1","dir2")

Diese Methode ist flexibler und wartbarer, Sie gruppieren Funktionen und es ist offensichtlicher, was jede Funktion tut. Außerdem verhindern Sie Namenskonflikte, z. B. kann die Funktionskopie in einem anderen importierten Modul (z. B. Netzwerkkopie) vorhanden sein, das Sie in Ihrem Code verwenden. Wenn Sie also den vollständigen Namen FileUtil.copy () verwenden, entfernen Sie das Problem und beide Kopierfunktionen kann nebeneinander verwendet werden.

Feuerphil
quelle
1
Um f1 (), f2 () usw. wie Sie zu verwenden, sollten Sie nicht vom Modulimport * und vom Nutzungsimport * verwenden?
Jblasco
@Jblasco Ich habe die Importanweisungen korrigiert, um die Verwirrung zu beseitigen. Ja, wenn Sie das Modul importieren, müssen Sie den Funktionen den Modulnamen voranstellen. dh Importmodul -> Modul.f1 () usw.
Firephil
Ich bin mit dieser Antwort nicht einverstanden; Python ist nicht Java. Das Problem des nicht verwaltbaren Codes tritt anscheinend nur aufgrund der absichtlichen Auswahl schlechter Namen im Beispiel auf. Wenn Sie stattdessen die FileUtilKlassenmethoden als Funktionen eines file_utilModuls replizieren würden, wäre dies vergleichbar und würde OOP nicht missbrauchen, wenn tatsächlich keine Objekte vorhanden sind (tatsächlich könnten Sie argumentieren, dass dies vorzuziehen ist, da Sie keine oder keine from file_util import FileUtilandere Ausführlichkeit haben). Namenskonflikte können im Verfahrenscode ebenfalls vermieden werden, indem import file_utilstattdessen statt from file_util import ....
ForgottenUmbrella
7

Ehrlich? Ich habe nie eine Verwendung für staticmethod oder classmethod gefunden. Ich habe noch keine Operation gesehen, die nicht mit einer globalen Funktion oder einer Instanzmethode ausgeführt werden kann.

Es wäre anders, wenn Python private und geschützte Mitglieder verwenden würde, ähnlich wie Java. In Java benötige ich eine statische Methode, um auf die privaten Mitglieder einer Instanz zugreifen zu können. In Python ist das selten notwendig.

Normalerweise sehe ich Leute, die statische Methoden und Klassenmethoden verwenden, wenn sie wirklich nur die Namespaces auf Modulebene von Python besser verwenden müssen.

Jason Baker
quelle
1
Privat: _variable_name und Protected: __variable_name
Bradley Kreider
1
Eine unverzichtbare Verwendung ist die setUpClass und die tearDownClass von unittest. Du benutzt Unittests, richtig? :)
dbn
7

Sie können damit generische Klassenmethoden schreiben, die Sie mit jeder kompatiblen Klasse verwenden können.

Beispielsweise:

@classmethod
def get_name(cls):
    print cls.name

class C:
    name = "tester"

C.get_name = get_name

#call it:
C.get_name()

Wenn Sie nicht verwenden @classmethod, können Sie dies mit dem Schlüsselwort self tun, es wird jedoch eine Instanz von Class benötigt:

def get_name(self):
    print self.name

class C:
    name = "tester"

C.get_name = get_name

#call it:
C().get_name() #<-note the its an instance of class C
noch
quelle
5

Ich habe früher mit PHP gearbeitet und mich kürzlich gefragt, was mit dieser Klassenmethode los ist. Das Python-Handbuch ist sehr technisch und in Worten sehr kurz, daher hilft es nicht, diese Funktion zu verstehen. Ich habe gegoogelt und gegoogelt und eine Antwort gefunden -> http://code.anjanesh.net/2007/12/python-classmethods.html .

Wenn Sie faul sind, darauf zu klicken. Meine Erklärung ist kürzer und unten. :) :)

In PHP (vielleicht kennen nicht alle von Ihnen PHP, aber diese Sprache ist so einfach, dass jeder verstehen sollte, wovon ich spreche) haben wir statische Variablen wie diese:


class A
{

    static protected $inner_var = null;

    static public function echoInnerVar()
    {
        echo self::$inner_var."\n";
    }

    static public function setInnerVar($v)
    {
        self::$inner_var = $v;
    }

}

class B extends A
{
}

A::setInnerVar(10);
B::setInnerVar(20);

A::echoInnerVar();
B::echoInnerVar();

Die Ausgabe erfolgt in beiden Fällen 20.

In Python können wir jedoch @classmethod decorator hinzufügen, und daher ist es möglich, Ausgabe 10 bzw. 20 zu haben. Beispiel:


class A(object):
    inner_var = 0

    @classmethod
    def setInnerVar(cls, value):
        cls.inner_var = value

    @classmethod
    def echoInnerVar(cls):
        print cls.inner_var


class B(A):
    pass


A.setInnerVar(10)
B.setInnerVar(20)

A.echoInnerVar()
B.echoInnerVar()

Klug, nicht wahr?

Drachenfels
quelle
Ein mögliches Problem mit Ihrem Python-Beispiel ist, dass wenn das weggelassen B.setInnerVar(20)wurde, es 10zweimal gedruckt wird (anstatt beim zweiten echoInnerBar () -Aufruf einen Fehler zu geben, für den no inner_vardefiniert wurde.
martineau
5

Klassenmethoden liefern einen "semantischen Zucker" (ich weiß nicht, ob dieser Begriff weit verbreitet ist) - oder "semantische Bequemlichkeit".

Beispiel: Sie haben eine Reihe von Klassen, die Objekte darstellen. Vielleicht möchten Sie die Klassenmethode haben all()oder find()schreiben User.all()oder User.find(firstname='Guido'). Das könnte natürlich mit Funktionen auf Modulebene geschehen ...

Pierre
quelle
In Ihrem Beispiel wird natürlich davon ausgegangen, dass die Klasse alle ihre Instanzen verfolgt und nach ihrer Erstellung darauf zugreifen kann - etwas, das nicht automatisch erfolgt.
Martineau
1
"semantischer Zucker" klingt nach einer guten Ergänzung zu "syntaktischem Zucker".
XTL
3

Was mich gerade von Ruby getroffen hat, ist diese sogenannte Klasse und eine sogenannte Instanzmethode nur eine Funktion mit semantischer Bedeutung ist, die auf ihren ersten Parameter angewendet wird, der stillschweigend übergeben wird, wenn die Funktion als Methode von aufgerufen wird ein Objekt (dhobj.meth() ).

Normalerweise muss dieses Objekt eine Instanz sein, aber der @classmethod Methodendekorator ändert die Regeln, um eine Klasse zu übergeben. Sie können eine Klassenmethode für eine Instanz aufrufen (es ist nur eine Funktion) - das erste Argument ist ihre Klasse.

Weil es nur ein ist Funktion handelt , kann sie in einem bestimmten Bereich (dh einer classDefinition) nur einmal deklariert werden . Es folgt daher als Überraschung für einen Rubyisten, dass Sie keine Klassenmethode und keine Instanzmethode mit demselben Namen haben können .

Bedenken Sie:

class Foo():
  def foo(x):
    print(x)

Du kannst anrufen foo eine Instanz

Foo().foo()
<__main__.Foo instance at 0x7f4dd3e3bc20>

Aber nicht in einer Klasse:

Foo.foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method foo() must be called with Foo instance as first argument (got nothing instead)

Fügen Sie nun hinzu @classmethod :

class Foo():
  @classmethod
  def foo(x):
    print(x)

Das Aufrufen einer Instanz übergibt jetzt ihre Klasse:

Foo().foo()
__main__.Foo

ebenso wie das Aufrufen einer Klasse:

Foo.foo()
__main__.Foo

Es ist nur die Konvention, die vorschreibt, dass wir selffür dieses erste Argument eine Instanzmethode verwenden undcls eine Klassenmethode verwenden. Ich habe beides hier nicht verwendet, um zu veranschaulichen, dass es nur ein Argument ist. In Ruby selfist ein Schlüsselwort.

Kontrast zu Ruby:

class Foo
  def foo()
    puts "instance method #{self}"
  end
  def self.foo()
    puts "class method #{self}"
  end
end

Foo.foo()
class method Foo

Foo.new.foo()
instance method #<Foo:0x000000020fe018>

Die Python-Klassenmethode ist nur eine dekorierte Funktion, und Sie können dieselben Techniken verwenden, um Ihre eigenen Dekoratoren zu erstellen . Eine dekorierte Methode umschließt die reale Methode (im Falle, dass @classmethodsie das zusätzliche Klassenargument übergibt). Die zugrunde liegende Methode ist immer noch vorhanden, versteckt, aber immer noch zugänglich .


Fußnote: Ich habe dies geschrieben, nachdem ein Namenskonflikt zwischen einer Klassen- und einer Instanzmethode meine Neugier geweckt hat. Ich bin weit entfernt von einem Python-Experten und hätte gerne Kommentare, wenn dies falsch ist.

Sternenhimmel
quelle
"was stillschweigend übergeben wird, wenn die Funktion als Methode eines Objekts aufgerufen wird" - ich glaube, das ist nicht genau. AFICT, in Python wird nichts "stillschweigend übergeben". IMO, Python ist in diesem Sinne viel vernünftiger als Ruby (außer super()). AFICT, die "Magie" passiert, wenn ein Attribut gesetzt oder gelesen wird. Der Aufruf obj.meth(arg)in Python (im Gegensatz zu Ruby) bedeutet einfach (obj.meth)(arg). Nichts wird stillschweigend irgendwohin übergeben, obj.methsondern ist nur ein aufrufbares Objekt, das ein Argument weniger akzeptiert als die Funktion, aus der es erstellt wurde.
Alexey
obj.methbedeutet wiederum einfach getattr(obj, "meth").
Alexey
Es ist sinnvoll, eine Antwort zu haben, die auf Personen zugeschnitten ist, die aus anderen gängigen Sprachen kommen. Eine Sache, die in dieser Konversation fehlt und die sie zusammenhält, ist die Vorstellung eines Python-Deskriptors . Funktionen sind Deskriptoren , und auf diese Weise wird das erste Argument "automatisch" an eine Instanz übergeben, wenn eine Funktion ein Attribut für die Klasse ist. Auf diese Weise werden auch Klassenmethoden implementiert, und im verknüpften HOWTO I wird eine reine Python-Implementierung bereitgestellt. Die Tatsache, dass es auch ein Dekorateur ist, ist eine Art
Nebeneffekt
2

Dies ist ein interessantes Thema. Ich gehe davon aus, dass die Python-Klassenmethode eher wie ein Singleton als wie eine Factory funktioniert (die eine produzierte Instanz einer Klasse zurückgibt). Der Grund, warum es sich um ein Singleton handelt, besteht darin, dass ein gemeinsames Objekt (das Wörterbuch) nur einmal für die Klasse erstellt wird, das jedoch von allen Instanzen gemeinsam genutzt wird.

Um dies hier zu veranschaulichen, ist ein Beispiel. Beachten Sie, dass alle Instanzen einen Verweis auf das einzelne Wörterbuch haben. Dies ist kein Factory-Muster, wie ich es verstehe. Dies ist wahrscheinlich sehr einzigartig für Python.

class M():
 @classmethod
 def m(cls, arg):
     print "arg was",  getattr(cls, "arg" , None),
     cls.arg = arg
     print "arg is" , cls.arg

 M.m(1)   # prints arg was None arg is 1
 M.m(2)   # prints arg was 1 arg is 2
 m1 = M()
 m2 = M() 
 m1.m(3)  # prints arg was 2 arg is 3  
 m2.m(4)  # prints arg was 3 arg is 4 << this breaks the factory pattern theory.
 M.m(5)   # prints arg was 4 arg is 5
Peter Moore
quelle
2

Ich habe mir einige Male die gleiche Frage gestellt. Und obwohl die Jungs hier versucht haben, es zu erklären, ist meiner Meinung nach die beste (und einfachste) Antwort, die ich gefunden habe, die Beschreibung der Class-Methode in der Python-Dokumentation.

Es wird auch auf die statische Methode verwiesen. Und falls jemand bereits Instanzmethoden kennt (was ich annehme), könnte diese Antwort das letzte Stück sein, um alles zusammenzufügen ...

Weitere und ausführlichere Informationen zu diesem Thema finden Sie auch in der Dokumentation: Die Standardtyphierarchie (scrollen Sie nach unten zum Abschnitt Instanzmethoden ).

Dee'Kej
quelle
1

@classmethodkann nützlich sein, um Objekte dieser Klasse einfach von externen Ressourcen aus zu instanziieren. Folgendes berücksichtigen:

import settings

class SomeClass:
    @classmethod
    def from_settings(cls):
        return cls(settings=settings)

    def __init__(self, settings=None):
        if settings is not None:
            self.x = settings['x']
            self.y = settings['y']

Dann in einer anderen Datei:

from some_package import SomeClass

inst = SomeClass.from_settings()

Der Zugriff auf inst.x ergibt den gleichen Wert wie die Einstellungen ['x'].

Psilocybin
quelle
0

Eine Klasse definiert natürlich eine Reihe von Instanzen. Und die Methoden einer Klasse arbeiten an den einzelnen Instanzen. Die Klassenmethoden (und Variablen) sind ein Ort, an dem andere Informationen, die sich auf die Menge der Instanzen beziehen, insgesamt aufgehängt werden können.

Wenn Ihre Klasse beispielsweise eine Gruppe von Schülern definiert, möchten Sie möglicherweise Klassenvariablen oder Methoden, die Dinge wie die Gruppe von Noten definieren, zu denen die Schüler gehören können.

Sie können auch Klassenmethoden verwenden, um Werkzeuge für die Arbeit am gesamten Satz zu definieren. Beispielsweise kann Student.all_of_em () alle bekannten Schüler zurückgeben. Wenn Ihre Instanz mehr Struktur als nur eine Menge hat, können Sie natürlich Klassenmethoden bereitstellen, um diese Struktur zu kennen. Students.all_of_em (Klasse = 'Junioren')

Techniken wie diese führen dazu, dass Mitglieder der Instanz in Datenstrukturen gespeichert werden, die in Klassenvariablen verwurzelt sind. Sie müssen darauf achten, dass die Speicherbereinigung dann nicht frustriert wird.

Ben Hyde
quelle