Wie kann ich auf “statische” Klassenvariablen innerhalb von Methoden zugreifen?

Lesezeit: 7 Minuten

Benutzeravatar von Ross Rogers
Ross Rogers

Wenn ich folgenden Code habe:

class Foo(object):
    bar = 1

    def bah(self):
        print(bar)
        
f = Foo()
f.bah()

Es klagt

NameError: Der globale Name „Bar“ ist nicht definiert

Wie kann ich auf Klasse/statische Variable zugreifen bar innerhalb der Methode bah?

  • Weitere Informationen zu Python und Statik finden Sie hier: stackoverflow.com/questions/68645/python-static-variable

    – Bettwyr

    1. April 2009 um 21:57 Uhr

Anstatt von bar verwenden self.bar oder Foo.bar. Zuordnung zu Foo.bar wird eine statische Variable erstellen und zuweisen self.bar erstellt eine Instanzvariable.

  • Foo.bar wird funktionieren, aber self.bar erstellt eine Instanzvariable, keine statische.

    – Bettwyr

    1. April 2009 um 21:55 Uhr

  • bedwyr, “print self.bar” erstellt keine Instanzvariablen (obwohl die Zuweisung an self.bar dies tut).

    – Konstantin

    1. April 2009 um 22:14 Uhr

  • @Constantin – Das war mir nicht klar, es ist eine interessante Unterscheidung. Danke für die Korrektur 🙂

    – Bettwyr

    3. April 2009 um 1:14 Uhr

  • Aber wenn Sie nicht beabsichtigen, dass es einen Ivar gibt, ist es klarer, Foo.classmember zu verwenden.

    – mk12

    13. September 2009 um 20:58 Uhr

  • Wenn Sie statische Variablen verwenden, ist es eine gute Idee, die Fallstricke von hier zu lesen: stackoverflow.com/questions/68645/… . @Constantin gibt einen der vielen Fallstricke.

    – Trevor Boyd Smith

    21. März 2017 um 16:27 Uhr


Benutzeravatar von vartec
vartec

Klassenmethode definieren:

class Foo(object):
    bar = 1
    @classmethod
    def bah(cls):    
        print cls.bar

Wenn jetzt bah() muss eine Instanzmethode sein (dh Zugriff auf sich selbst haben), können Sie immer noch direkt auf die Klassenvariable zugreifen.

class Foo(object):
    bar = 1
    def bah(self):    
        print self.bar

  • Warum nicht einfach Foo.bar statt self.__class__.bar?

    – mk12

    13. September 2009 um 20:59 Uhr

  • @Mk12: Wenn Sie Klassenvererbung haben, könnte sich eine “Klassenvariable” in einer Basisklasse oder einer Unterklasse befinden. Auf welche möchten Sie sich beziehen? Hängt davon ab, was Sie versuchen zu tun. Foo.bar würde immer auf ein Attribut der angegebenen Klasse verweisen – die eine Basisklasse oder eine Unterklasse sein könnte. self.__class__.bar würde sich auf die Klasse beziehen, von der die Instanz ein Typ ist.

    – Craig McQueen

    11. Dezember 2009 um 4:47 Uhr

  • Jetzt haben wir den unglücklichen Punkt erreicht, an dem wir uns der Details der Sprache so bewusst werden, dass wir zwischen zwei fein aufeinander abgestimmten Anwendungsfällen unterscheiden können. Es hängt in der Tat davon ab, was Sie tun möchten, aber viele Leute werden sich nicht um solche Feinheiten kümmern.

    – Holdenweb

    14. Dezember 2011 um 10:19 Uhr

  • Übrigens, dies ist eine SELTENE Verwendung von “Klassenvariable”. Viel häufiger wird es in einer bestimmten Klasse definiert, hier Foo. Dies sind nützliche Informationen für einige fortgeschrittene Programmiersituationen. Aber mit ziemlicher Sicherheit nicht das, was die ursprüngliche Frage als Antwort wollte (jeder, der DIESE Antwort braucht, weiß bereits, wie man Foo.bar macht). +1, weil ich daraus etwas gelernt habe.

    – WerkzeugmacherSteve

    25. November 2013 um 17:05 Uhr


  • Ich lerne, wann Klassenvariablen und -methoden verwendet werden (im Gegensatz zu Instanzvariablen und -methoden). Wenn Sie in einer Instanzmethode auf eine Klassenvariable zugreifen möchten, ist es dann notwendig, self.__class__.bar zu verwenden? Mir ist aufgefallen, dass self.bar funktioniert, obwohl bar eine Klassenvariable und keine Instanzvariable ist.

    – Rechnung

    29. März 2015 um 18:30 Uhr

Benutzeravatar von David Berger
David Berger

Wie bei allen guten Beispielen haben Sie das, was Sie eigentlich versuchen, vereinfacht. Das ist gut, aber es ist erwähnenswert, dass Python eine hat viel der Flexibilität, wenn es um Klassen- und Instanzvariablen geht. Dasselbe gilt für Methoden. Für eine gute Liste der Möglichkeiten empfehle ich die Lektüre Michael Fötsch’ neu gestaltete Klasseneinführunginsbesondere die Abschnitte 2 bis 6.

Eine Sache, die viel Arbeit erfordert, um sich am Anfang daran zu erinnern, ist das Python ist nicht Java. Mehr als nur ein Klischee. In Java wird eine ganze Klasse kompiliert, was die Namensraumauflösung sehr einfach macht: Alle außerhalb einer Methode (irgendwo) deklarierten Variablen sind Instanzvariablen (oder, falls statisch, Klassenvariablen) und implizit innerhalb von Methoden zugänglich.

Bei Python lautet die Faustregel, dass es drei Namespaces gibt, die der Reihe nach nach Variablen durchsucht werden:

  1. Die Funktion/Methode
  2. Das aktuelle Modul
  3. Einbauten

{begin pedagogy}

Hiervon gibt es begrenzte Ausnahmen. Der wichtigste, der mir auffällt, ist, dass beim Laden einer Klassendefinition die Klassendefinition ihr eigener impliziter Namensraum ist. Dies dauert jedoch nur so lange, wie das Modul geladen wird, und wird innerhalb einer Methode vollständig umgangen. Daher:

>>> class A(object):
        foo = 'foo'
        bar = foo


>>> A.foo
'foo'
>>> A.bar
'foo'

aber:

>>> class B(object):
        foo = 'foo'
        def get_foo():
            return foo
        bar = get_foo()



Traceback (most recent call last):
  File "<pyshell#11>", line 1, in <module>
    class B(object):
  File "<pyshell#11>", line 5, in B
    bar = get_foo()
  File "<pyshell#11>", line 4, in get_foo
    return foo
NameError: global name 'foo' is not defined

{end pedagogy}

Am Ende ist die Sache, an die Sie sich erinnern sollten, dass Sie tun Zugriff auf alle Variablen haben, auf die Sie zugreifen möchten, aber wahrscheinlich nicht implizit. Wenn Ihre Ziele einfach und geradlinig sind, reicht es wahrscheinlich aus, sich für Foo.bar oder self.bar zu entscheiden. Wenn Ihr Beispiel komplizierter wird oder Sie ausgefallene Dinge wie Vererbung machen möchten (Sie können statische Methoden/Klassenmethoden erben!) oder Ihnen die Idee, auf den Namen Ihrer Klasse innerhalb der Klasse selbst zu verweisen, falsch erscheint, probieren Sie es aus das von mir verlinkte Intro.

  • IIRC, es werden technisch gesehen 3(+) Namespaces durchsucht – funktionslokal, modul/global und eingebaut. Verschachtelte Bereiche bedeuten, dass mehrere lokale Bereiche durchsucht werden können, aber das ist einer der Ausnahmefälle. (…)

    – Jeff Shannon

    2. April 2009 um 8:52 Uhr

  • Außerdem würde ich vorsichtig sein, „Hauptmodul“ zu sagen, da es das enthaltende Modul der Funktion ist, das durchsucht wird, nicht das hauptsächlich Modul … Und das Nachschlagen des Attributs aus einer Instanzreferenz ist eine andere Sache, aber diese Antwort erklärt es warum Sie benötigen die Instanz-/Klassenreferenz.

    – Jeff Shannon

    2. April 2009 um 8:57 Uhr

Benutzeravatar von Allan Mwesigwa
Allan Mwesigwa

class Foo(object):
     bar = 1
     def bah(self):
         print Foo.bar

f = Foo() 
f.bah()

Benutzeravatar von Parik Chudasma
Parik Chudasma

bar ist Ihre statische Variable und Sie können mit darauf zugreifen Foo.bar.

Grundsätzlich müssen Sie Ihre statische Variable mit dem Klassennamen qualifizieren.

  • Erwägen Sie, weitere Informationen hinzuzufügen, um Ihre Antwort zu erweitern, oder bearbeiten Sie andere Antworten, um dieses Detail hinzuzufügen.

    – Benutzer1010

    5. Januar 2021 um 18:59 Uhr

Sie können darauf zugreifen Klassenvariablen durch Objekt und direkt vorbei Klassenname von außerhalb oder innerhalb der Klasse und grundsätzlich sollten Sie darauf zugreifen Klassenvariablen direkt vorbei Klassenname denn wenn es welche gibt gleichnamige Klassen- und Instanzvariablen, gleichnamige Instanzvariable wird dabei priorisiert gleichnamige Instanzvariable wird ignoriert, wenn auf das Objekt zugegriffen wird. Also verwenden Klassenname ist sicherer als die Verwendung Objekt zugreifen Klassenvariablen.

Beispielsweise können Sie auf die Klassenvariable nach Objekt und direkt nach Klassenname von außerhalb der Klasse zugreifen, wie unten gezeigt:

class Person:
    name = "John" # Class variable

obj = Person()
print(obj.name) # By object
print(Person.name) # By class name

Ausgabe:

John
John

Wenn Sie jedoch die Instanzvariable mit dem gleichen Namen wie die Klassenvariable nach Objekt hinzufügen:

class Person:
    name = "John" # Class variable

obj = Person()
obj.name = "Tom" # Adds the same name instance variable as class variable
print(obj.name) # By object
print(Person.name) # By class name

Oder wenn Sie die Instanzvariable mit dem gleichen Namen wie die Klassenvariable by hinzufügen self in __init__():

class Person:
    name = "John" # Class variable
    
    def __init__(self, name):
        self.name = name # Adds the same name instance variable as class variable

obj = Person("Tom")
print(obj.name) # By object
print(Person.name) # By class name

Die gleichnamige Instanzvariable wird priorisiert, wenn auf das Objekt zugegriffen wird:

Tom  # By object
John # By class name

Und Sie können auch auf die Klassenvariable zugreifen self und direkt nach Klassenname aus dem Inneren der Instanzmethode, wie unten gezeigt:

class Person:
    name = "John" # Class variable
        
    def test(self): # Instance method
        print(self.name) # By "self"
        print(Person.name) # By class name

obj = Person()
obj.test()

Ausgabe:

John
John

Wenn Sie jedoch die Instanzvariable mit dem gleichen Namen wie die Klassenvariable nach Objekt hinzufügen:

class Person:
    name = "John" # Class variable
        
    def test(self): # Instance method
        print(self.name) # By "self"
        print(Person.name) # By class name

obj = Person()
obj.name = "Tom" # Adds the same name instance variable as the class variable
obj.test()

Oder wenn Sie die Instanzvariable mit dem gleichen Namen wie die Klassenvariable by hinzufügen self in __init__():

class Person:
    name = "John" # Class variable
    
    def __init__(self, name):
        self.name = name # Adds the same name instance variable as the class variable
        
    def test(self): # Instance method
        print(self.name) # By "self"
        print(Person.name) # Directly by class name

obj = Person("Tom")
obj.test()

Die gleichnamige Instanzvariable wird priorisiert, wenn auf sie zugegriffen wird self:

Tom  # By "self"
John # By class name

  • Erwägen Sie, weitere Informationen hinzuzufügen, um Ihre Antwort zu erweitern, oder bearbeiten Sie andere Antworten, um dieses Detail hinzuzufügen.

    – Benutzer1010

    5. Januar 2021 um 18:59 Uhr

1436130cookie-checkWie kann ich auf “statische” Klassenvariablen innerhalb von Methoden zugreifen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy