Unterschied zwischen Variablen innerhalb und außerhalb von __init__() (Klassen- und Instanzattribute)
Lesezeit: 8 Minuten
Teifion
Gibt es neben dem Namen überhaupt einen Unterschied zwischen diesen Klassen?
class WithClass ():
def __init__(self):
self.value = "Bob"
def my_func(self):
print(self.value)
class WithoutClass ():
value = "Bob"
def my_func(self):
print(self.value)
Macht es einen Unterschied, ob ich die nutze oder nicht __init__ Methode zum Deklarieren der Variablen value?
Meine Hauptsorge ist, dass ich es auf eine Weise verwende, wenn mir das später weitere Probleme bereiten wird.
Eine ausführliche Antwort mit Beispielen in der doppelten Frage: stackoverflow.com/a/9056994/911945
– Anton Tarasenko
27. Oktober 2018 um 15:23 Uhr
S. Lott
Variables Set außen __init__ gehören zur Klasse. Sie werden von allen Instanzen geteilt.
Innerhalb erstellte Variablen __init__ (und alle anderen Methodenfunktionen) und mit vorangestellt self. gehören zur Objektinstanz.
Das ist nicht das, was Python für mich tut. Listen/Diktate/usw. werden von allen Instanzen gemeinsam genutzt, wenn Sie sie nicht in erstellen __init__().
– zu viel php
8. Oktober 2009 um 11:43 Uhr
@too much php: Alle Variablen der Klassenmethode (unabhängig von der Veränderlichkeit – Listen und Diktate sind veränderbar) werden geteilt. Bei unveränderlichen Objekten ist die gemeinsame Nutzung nicht interessant. Bei veränderlichen Objekten (Listen und Diktate) ist die gemeinsame Nutzung von Bedeutung.
– S. Lott
8. Oktober 2009 um 11:58 Uhr
Ich vermutete, dass dies der Fall sein könnte, dachte mir aber, dass es von der Frage selbst ablenken könnte, wenn ich meine Annahmen darlege. Prost auf die Klärung 🙂
– Teifion
8. Oktober 2009 um 18:54 Uhr
Ich dachte, das war, was passierte, aber es war mir sehr unklar. Danke für die Klärung.
– dimo414
22. Februar 2011 um 10:49 Uhr
Das ist etwas irreführend. EIN varnameVariablensatz außerhalb der drin gehört zur Klasse und kann über gelesen werden self.varname denselben Wert für alle Instanzen erzeugen. Wenn jedoch ein Wert über eine Instanzreferenz zugewiesen wird (wie in self.varname = X) a Neu self.varname wird erstellt nur für diesen Fall, wodurch die Klassenvariable verdeckt wird. Die Klassenvariable bleibt über eine Klassenreferenz erreichbar (zB: WithClass.varname). Und Klassenvariablen können auch von jeder Methode aus festgelegt werden, indem der Klassenname vorangestellt wird (WithClass.myvar = X) anstelle einer Instanzreferenz (self.myvar = X).
– Lobotomik
8. März 2017 um 11:26 Uhr
Ohne Selbst
Erstellen Sie einige Objekte:
class foo(object):
x = 'original class'
c1, c2 = foo(), foo()
Ich kann die c1-Instanz ändern, und die c2-Instanz wird davon nicht betroffen:
Beachten Sie, dass dieses Beispiel nur für neue Typklassen funktioniert, bei alten haben sie das gleiche Ergebnis
– Abdelouahab
4. Januar 2015 um 0:57 Uhr
@Abdelouahab, ist das so? Ich habe es mit alten Stilklassen versucht und das gleiche Ergebnis wie neue Stilobjekte erhalten. Python 2.7.8
– Bauer
6. August 2015 um 1:01 Uhr
Alejandro
Ich möchte etwas zu den Antworten hinzufügen, die ich in diesem Thread und diesem Thread (der auf diesen verweist) gelesen habe.
Haftungsausschluss: Diese Bemerkungen stammen von den Experimenten, die ich durchgeführt habe
Variablen außerhalb __init__:
Dies sind in der Tat statische Klassenvariablen und sind daher für alle Instanzen der Klasse zugänglich.
Variablen drin __init__:
Der Wert dieser Instanzvariablen sind nur für die jeweilige Instanz zugänglich (über die self Hinweis)
Mein Beitrag:
Eine Sache, die Programmierer bei der Verwendung beachten müssen statische Klassenvariablen ist, dass sie von beschattet werden können Instanzvariablen (Wenn Sie auf die zugreifen statische Klassenvariablen durch die self Hinweis).
Erläuterung:
Früher dachte ich, dass beide Arten der Deklaration der Variablen genau gleich seien (dumm), und das lag teilweise daran, dass ich über die auf beide Arten von Variablen zugreifen konnte self Hinweis. Als ich jetzt in Schwierigkeiten geriet, habe ich das Thema recherchiert und aufgeräumt.
Das Problem mit dem Zugriff statische Klassenvariablen durch die self Referenz ist, dass es nur auf die verweist statische Klassenvariable wenn es keine gibt Instanzvariable mit demselben Namen, und um die Sache noch schlimmer zu machen, versuchen Sie, a neu zu definieren statische Klassenvariable durch die self Verweis funktioniert nicht, weil ein Instanzvariable entsteht, die dann das bisher Zugängliche überschattet statische Klassenvariable.
Um dieses Problem zu umgehen, sollten Sie immer referenzieren statische Klassenvariablen durch den Namen der Klasse.
Beispiel:
#!/usr/bin/env python
class Foo:
static_var="every instance has access"
def __init__(self,name):
self.instance_var="I am %s" % name
def printAll(self):
print 'self.instance_var = %s' % self.instance_var
print 'self.static_var = %s' % self.static_var
print 'Foo.static_var = %s' % Foo.static_var
f1 = Foo('f1')
f1.printAll()
f1.static_var="Shadowing static_var"
f1.printAll()
f2 = Foo('f2')
f2.printAll()
Foo.static_var="modified class"
f1.printAll()
f2.printAll()
Ausgabe:
self.instance_var = I am f1
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = every instance has access
self.instance_var = I am f2
self.static_var = every instance has access
Foo.static_var = every instance has access
self.instance_var = I am f1
self.static_var = Shadowing static_var
Foo.static_var = modified class
self.instance_var = I am f2
self.static_var = modified class
Foo.static_var = modified class
Ich hoffe, das ist hilfreich für jemanden
Das ist hier die wichtigste Antwort
– gowthz
27. Dezember 2021 um 10:13 Uhr
Neil
nach der Antwort von S.Lott werden Klassenvariablen an die Metaklasse übergeben Neu -Methode und kann über das Wörterbuch aufgerufen werden, wenn eine Metaklasse definiert ist. Auf Klassenvariablen kann also bereits zugegriffen werden, bevor Klassen erstellt und instanziiert werden.
zum Beispiel:
class meta(type):
def __new__(cls,name,bases,dicto):
# two chars missing in original of next line ...
if dicto['class_var'] == 'A':
print 'There'
class proxyclass(object):
class_var="A"
__metaclass__ = meta
...
...
Im obigen Code hat die User-Klasse 3 globale Variablen, jede mit dem Wert „none“. u1 ist das Objekt, das durch Instanziieren dieser Klasse erstellt wird. Die Methode print_var gibt den Wert von Klassenvariablen der Klasse User und Objektvariablen des Objekts u1 aus. In der unten gezeigten Ausgabe wird jede der Klassenvariablen User.email, User.firstname und User.lastname Wert hat 'none'während die Objektvariablen u1.email, u1.firstname und u1.lastname Werte haben 'abc@xyz', 'first' und 'last'.
Wir lösen im Wesentlichen aus __init__ das wird die initialisieren Instanzvariablen des neu geschaffenen Employee. Das bedeutet, dass _first_name, _last_name und _position sind explizite Parameter des Spezifischen my_employee Beispiel.
Ebenfalls, Mitgliedsfunktionen Informationen zurückgeben oder den Status einer bestimmten Instanz ändern.
Jetzt jede außerhalb des Konstruktors definierte Variable __init__ gelten als Klassenvariablen. Diese Variablen werden von allen Instanzen der Klasse gemeinsam genutzt.
john = Employee("John", "Wood", "Software Engineer")
bob = Employee("Bob", "Smith", "DevOps Engineer0")
print(john.get_full_name())
print(bob.get_full_name())
print(john.company)
print(bob.company)
>>> John Wood
>>> Bob Smith
>>> mycompany.com
>>> mycompany.com
Sie können auch verwenden Klassenmethoden um die Klassenvariable für alle Instanzen der Klasse zu ändern. Zum Beispiel:
@classmethod
def change_my_companys_name(cls, name):
cls.company = name
und nun change_my_companys_name()
bob.change_my_companys_name("mynewcompany.com")
wirkt sich auf alle Instanzen der Klasse aus Employee:
class inside:
def __init__(self):
self.l = []
def insert(self, element):
self.l.append(element)
class outside:
l = [] # static variable - the same for all instances
def insert(self, element):
self.l.append(element)
def main():
x = inside()
x.insert(8)
print(x.l) # [8]
y = inside()
print(y.l) # []
# ----------------------------
x = outside()
x.insert(8)
print(x.l) # [8]
y = outside()
print(y.l) # [8] # here is the difference
if __name__ == '__main__':
main()
Aber wenn ich L verwende, um ein int zu speichern, kann ich das L sogar für das äußere x ändern, ohne das L des äußeren y zu ändern …
– Oskar Hofmann
5. Juli 2021 um 11:29 Uhr
13989400cookie-checkUnterschied zwischen Variablen innerhalb und außerhalb von __init__() (Klassen- und Instanzattribute)yes
Eine ausführliche Antwort mit Beispielen in der doppelten Frage: stackoverflow.com/a/9056994/911945
– Anton Tarasenko
27. Oktober 2018 um 15:23 Uhr