Was ist der Zweck des Wortes "Selbst"?

1130

Was ist der Zweck des selfWortes in Python? Ich verstehe, dass es sich auf das spezifische Objekt bezieht, das aus dieser Klasse erstellt wurde, aber ich kann nicht verstehen, warum es explizit zu jeder Funktion als Parameter hinzugefügt werden muss. Zur Veranschaulichung kann ich in Ruby Folgendes tun:

class myClass
    def myFunc(name)
        @name = name
    end
end

Was ich ganz leicht verstehe. In Python muss ich jedoch Folgendes einschließen self:

class myClass:
    def myFunc(self, name):
        self.name = name

Kann mir jemand das erklären? Es ist nicht etwas, auf das ich in meiner (zugegebenermaßen begrenzten) Erfahrung gestoßen bin.

Richzilla
quelle
111
Vielleicht finden Sie diesen Aufsatz "Warum explizites Selbst bleiben muss" von Guido van Rossum interessant
unutbu
14
Siehe auch "Warum muss 'self' explizit in Methodendefinitionen und Aufrufen verwendet werden": docs.python.org/faq/…
unutbu
37
"Was ich ganz leicht verstehe" --- Ganz subjektiv, findest du nicht? Was macht @nameintuitiver als self.name? Letzteres, IMO, ist intuitiver.
Santa
14
Das ist der Hauptunterschied zwischen einer Funktion und einer Klassenmethode. Eine Funktion schwebt frei und unbelastet. Eine Klassenmethode (Instanzmethode) muss ihre übergeordneten (und übergeordneten Eigenschaften) kennen, daher müssen Sie der Methode einen Verweis auf die übergeordnete Klasse (als self ) übergeben. Es ist nur eine implizite Regel weniger, die Sie verinnerlichen müssen, bevor Sie OOP verstehen. Andere Sprachen wählen syntaktischen Zucker gegenüber semantischer Einfachheit, Python ist keine andere Sprache.
Evan Plaice
9
Ich denke nicht, dass "explizit ist besser als implizit" diese Designentscheidung wirklich gut erklärt. @foound self.foosind ebenso explizit, da keine implizite Auflösung erfolgen muss (z. B. können in C ++ auf Instanzmitglieder "implizit" zugegriffen werden, ohne "explizit" Namespaces zu verwenden). Der einzige Unterschied besteht darin, dass Ruby eine neue Semantik (@) einführt, Python jedoch nicht. Ob eine neue Semantik die vermiedene Ausführlichkeit wert war oder nicht, ist rein subjektiv. Es sollte jedoch beachtet werden, dass die meisten modernen Sprachen hier ein Konzept einführen (z. B. PHPs $ this, JS's this).
Jing

Antworten:

710

Der Grund, den Sie verwenden müssen, self.ist, dass Python die @Syntax nicht verwendet , um auf Instanzattribute zu verweisen. Python entschied Methoden in einer Art und Weise zu tun , dass die Instanz zu dem macht die Methode gehört werden weitergegeben automatisch, aber nicht empfangen automatisch: der erste Parameter von Methoden der Instanz ist die Methode aufgerufen wird. Das macht Methoden völlig gleich wie Funktionen und überlässt es Ihnen, den tatsächlichen Namen zu verwenden (obwohl dies selfdie Konvention ist und die Leute Sie im Allgemeinen missbilligen, wenn Sie etwas anderes verwenden.). Dies selfist nichts Besonderes für den Code, sondern nur ein anderes Objekt .

Python hätte etwas anderes tun können, um normale Namen von Attributen zu unterscheiden - eine spezielle Syntax wie Ruby oder Deklarationen wie C ++ und Java oder vielleicht etwas noch anderes -, aber das tat es nicht. Python ist alles, um Dinge explizit zu machen, um klar zu machen, was was ist, und obwohl es nicht überall funktioniert, macht es es zum Beispiel für Attribute. Aus diesem Grund muss das Zuweisen zu einem Instanzattribut wissen, welcher Instanz zugewiesen werden soll, und aus diesem Grund muss es zugewiesen werden self..

Thomas Wouters
quelle
23
@Georg: clsbezieht sich auf das Klassenobjekt, nicht auf das
Instanzobjekt
17
@ SilentGhost: Eigentlich ist der Name des ersten Parameters so, wie Sie es möchten. Bei Klassenmethoden ist die Konvention zu verwenden clsund selfwird konventionell für beispielsweise Methoden verwendet. Wenn ich wollte, könnte ich selffür Klassenmethoden und clszum Beispiel Methoden verwenden. Ich könnte auch verwenden bobund fnordwenn ich möchte.
SingleNegationElimination
67
Ich finde es interessant, dass die Community nicht thisstatt gewählt hat self. Hat selfeine Geschichte, die mir in älteren Programmiersprachen nicht bekannt ist?
Jules GM
24
@ Julius Der selfstammt aus den Konventionen von Modula-3. Weitere Details zu dieser Auswahl finden Sie in dieser Antwort . (Haftungsausschluss: es ist meins).
Bakuriu
9
@ Julius Das selfSchlüsselwort (Smalltalk, 1980) ist älter als das thisSchlüsselwort (aus C ++). Siehe: stackoverflow.com/questions/1079983/…
Wes Turner
425

Nehmen wir eine einfache Vektorklasse:

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

Wir wollen eine Methode, die die Länge berechnet. Wie würde es aussehen, wenn wir es innerhalb der Klasse definieren wollten?

    def length(self):
        return math.sqrt(self.x ** 2 + self.y ** 2)

Wie sollte es aussehen, wenn wir es als globale Methode / Funktion definieren würden?

def length_global(vector):
    return math.sqrt(vector.x ** 2 + vector.y ** 2)

Die gesamte Struktur bleibt also gleich. Wie kann ich das nutzen? Wenn wir für einen Moment annehmen, dass wir keine lengthMethode für unsere VectorKlasse geschrieben haben, könnten wir dies tun:

Vector.length_new = length_global
v = Vector(3, 4)
print(v.length_new()) # 5.0

Dies funktioniert, weil der erste Parameter von length_global, als selfParameter in wiederverwendet werden kann length_new. Dies wäre ohne eine explizite nicht möglich self.


Eine andere Möglichkeit, die Notwendigkeit des Expliziten selfzu verstehen, besteht darin, zu sehen, wo Python syntaktischen Zucker hinzufügt. Wenn Sie daran denken, dass im Grunde ein Anruf wie

v_instance.length()

wird intern umgewandelt in

Vector.length(v_instance)

Es ist leicht zu erkennen, wo das selfpasst. Sie schreiben keine Instanzmethoden in Python. Was Sie schreiben, sind Klassenmethoden, die eine Instanz als ersten Parameter verwenden müssen. Daher müssen Sie den Instanzparameter explizit irgendwo platzieren.

Debilski
quelle
4
Vector.length_new = length_global ... Ich habe tatsächlich begonnen, eine solche Syntax in meinen Klassendeklarationen zu verwenden. Wenn ich nur einige der Methoden von einer anderen Klasse erben möchte, kopiere ich einfach explizit den Verweis auf die Methoden.
Jeeyoung Kim
2
Wäre es fair zu sagen, dass die "Instanzmethode" von Python einfach ein syntaktischer Zucker statischer globaler Methoden (wie in Java oder C ++) ist, bei dem ein Instanzobjekt übergeben wird, um mehrere Attribute zu verpacken? --- Nun, das ist halbwegs wahr, da im Polymorphismus der wichtigere Zweck von "dies" (wie in Java) oder "Selbst" darin besteht, Ihnen die korrekte Implementierung von Methoden zu geben. Python hat das. Der Aufruf von myobj.someMethod () entspricht also TheClassOfMyObj.someMethod (myobj) in Python. Beachten Sie, dass "TheClassOfMyObj" automatisch von Python aus "self" herausgefunden wird, sonst müssten Sie das herausfinden.
Teddy Teddy
3
Tatsächlich sind Instanzmethoden nicht nur Klassenmethoden, sondern Methoden sind nur Funktionen, die Mitglieder einer Klasse sind, wie das Vector.length_new = length_globalzeigt.
RussW
1
"Dies funktioniert, da der erste Parameter von length_global als self-Parameter in length_new wiederverwendet werden kann. Dies wäre ohne ein explizites self nicht möglich." - Es würde genauso funktionieren. es würde für das implizite Selbst wiederverwendet werden ... das zweite Beispiel ist eine Zirkelschlussfolgerung - Sie müssen das Selbst explizit dort platzieren, weil Python das explizite Selbst benötigt.
Karoly Horvath
1
@KarolyHorvath: Sicher, es wäre auch möglich, eine Sprache mit einem Modell zu haben, in dem intern definierte Methoden kein explizites Selbst benötigen, extern definierte Methoden jedoch. Aber ich würde sagen, dass es in beiden Fällen eine gewisse Konsequenz gibt, das explizite Selbst zu fordern, was es zu einem legitimen Grund macht, dies auf diese Weise zu tun. Andere Sprachen können andere Ansätze wählen.
Debilski
422

Angenommen, Sie haben eine Klasse, ClassAdie eine Methode enthält, methodAdie wie folgt definiert ist:

def methodA(self, arg1, arg2):
    # do something

und ObjectAist eine Instanz dieser Klasse.

Wenn ObjectA.methodA(arg1, arg2)es jetzt aufgerufen wird, konvertiert Python es intern für Sie als:

ClassA.methodA(ObjectA, arg1, arg2)

Die selfVariable bezieht sich auf das Objekt selbst.

Arjun Sreedharan
quelle
94
Ich habe alle anderen Antworten gelesen und irgendwie verstanden, ich habe diese gelesen und dann hat alles Sinn gemacht.
Seth
3
Das hat es für mich geschafft!
Bernard 'Beta Berlin' Parah
2
Warum nicht diese Eingeweide im Inneren behalten, wie es Ruby tut?
Cees Timmerman
Aber in der __init __ (Selbst-) Methode akzeptiert es sich selbst. Wie verweist es dann auf sich selbst, auch ohne das Objekt zu erstellen?
Saurav
Im Ernst, dies ist viel besser als Debilskis Beispiel, da es nicht übermäßig komplex ist und die Leute möglicherweise nicht mit Vektoren vertraut sind.
NoName
215

Wenn Objekte instanziiert werden, wird das Objekt selbst an den Parameter self übergeben.

Geben Sie hier die Bildbeschreibung ein

Aus diesem Grund sind die Daten des Objekts an das Objekt gebunden. Im Folgenden finden Sie ein Beispiel dafür, wie Sie die Daten der einzelnen Objekte visualisieren möchten. Beachten Sie, wie 'self' durch den Objektnamen ersetzt wird. Ich sage nicht, dass dieses Beispieldiagramm unten völlig genau ist, aber es dient hoffentlich einem Zweck bei der Visualisierung des Gebrauchs des Selbst.

Geben Sie hier die Bildbeschreibung ein

Das Objekt wird an den Parameter self übergeben, damit das Objekt seine eigenen Daten behalten kann.

Obwohl dies möglicherweise nicht ganz korrekt ist, denken Sie an den Prozess des Instanziierens eines Objekts wie folgt: Wenn ein Objekt erstellt wird, verwendet es die Klasse als Vorlage für seine eigenen Daten und Methoden. Ohne einen eigenen Namen an den Parameter self zu übergeben, bleiben die Attribute und Methoden in der Klasse als allgemeine Vorlage erhalten und werden nicht auf das Objekt verwiesen (zu diesem gehören). Wenn Sie also den Namen des Objekts an den Parameter self übergeben, bedeutet dies, dass 100 Objekte, die aus einer Klasse instanziiert wurden, alle ihre eigenen Daten und Methoden verfolgen können.

Siehe die Abbildung unten:

Geben Sie hier die Bildbeschreibung ein

sw123456
quelle
Hey, wenn sie von "bob.name ()" Bobs Attribute zum Beispiel den Zugriff, die Sie tatsächlich accesing Bob (). Self.name so von der 'sprechen init ' richtig?
udarH3
3
Wenn Sie bob.name () in den obigen Kommentar schreiben, implizieren Sie, dass bob eine Methode namens name () hat, da Sie nach name Klammern hinzugefügt haben. In diesem Beispiel gibt es jedoch keine solche Methode. 'bob.name' (ohne Klammer) greift direkt über die Methode init (Konstruktor) auf das Attribut name zu. Wenn die Sprechmethode von bob aufgerufen wird, greift diese Methode auf das Namensattribut zu und gibt es in einer print-Anweisung zurück. Hoffe das hilft.
sw123456
3
Nein, Sie erhalten den Wert von self.name, der für das Bob-Objekt tatsächlich bob.name ist, da der Name des Objekts beim Erstellen (instanziiert) an den Parameter self übergeben wird. Hoffe wieder, das hilft. Fühlen Sie sich frei, den Hauptbeitrag zu verbessern, wenn dies der Fall ist.
sw123456
2
Der Name wird bei der Instanziierung self.name zugewiesen. Nachdem ein Objekt erstellt wurde, werden allen Variablen, die zum Objekt gehören, die Präfixe 'self' vorangestellt. Denken Sie daran, dass self beim Erstellen aus der Klasse durch den Namen des Objekts ersetzt wird.
sw123456
5
So erklärst du Sachen! gute Arbeit :)
Penta
80

Ich mag dieses Beispiel:

class A: 
    foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: [5]

class A: 
    def __init__(self): 
        self.foo = []
a, b = A(), A()
a.foo.append(5)
b.foo
ans: []
kame
quelle
18
also vars ohne selbst sind einfach statische vars der klasse, wie in java
teddy teddy
5
teddy teddy, du bist nicht ganz richtig. Das Verhalten (statisch oder nicht statisch) hängt nicht nur vom selfVariablentyp ab, sondern auch vom Variablentyp. Versuchen Sie, das erste Beispiel mit einer einfachen Ganzzahl anstelle einer Liste zu erstellen. Das Ergebnis wäre ganz anders.
Konstantin
2
Eigentlich ist meine Frage dabei, warum Sie a.fooim ersten Beispiel sagen dürfen und nicht A.foo? Gehört eindeutig foozur Klasse ...
Radon Rosborough
Sie können statische Elemente aus Instanzen des Objekts in den meisten Sprachen aufrufen. Warum ist das überraschend?
Paarth
2
@RadonRosborough Weil im ersten Beispiel aund bbeide Bezeichnungen (oder Zeiger) für A()(die Klasse) sind. a.fooverweist auf die A().fooKlassenmethode. Im zweiten Beispiel awird jedoch eine Referenz auf eine Instanz von A(), wie dies der Fall ist b. Jetzt, da es sich um Instanzen anstelle des Klassenobjekts selbst handelt, ermöglicht self der fooMethode, die Instanzen zu bearbeiten.
LegendaryDude
40

Ich werde mit Code demonstrieren, der keine Klassen verwendet :

def state_init(state):
    state['field'] = 'init'

def state_add(state, x):
    state['field'] += x

def state_mult(state, x):
    state['field'] *= x

def state_getField(state):
    return state['field']

myself = {}
state_init(myself)
state_add(myself, 'added')
state_mult(myself, 2)

print( state_getField(myself) )
#--> 'initaddedinitadded'

Klassen sind nur eine Möglichkeit, um zu vermeiden, dass dieser "Status" ständig übergeben wird (und andere nette Dinge wie Initialisierung, Klassenzusammensetzung, die selten benötigten Metaklassen und die Unterstützung benutzerdefinierter Methoden zum Überschreiben von Operatoren).

Lassen Sie uns nun den obigen Code mithilfe der integrierten Python-Klassenmaschinerie demonstrieren, um zu zeigen, wie es im Grunde dasselbe ist.

class State(object):
    def __init__(self):
        self.field = 'init'
    def add(self, x):
        self.field += x
    def mult(self, x):
        self.field *= x

s = State()
s.add('added')    # self is implicitly passed in
s.mult(2)         # self is implicitly passed in
print( s.field )

[hat meine Antwort von einer doppelten geschlossenen Frage migriert]

Ninjagecko
quelle
1
Ich wünschte, Python würde die Handler genauso beschönigen wie Ruby.
Cees Timmerman
20

Die folgenden Auszüge stammen aus der Python-Dokumentation zu self :

Wie in Modula-3 gibt es keine Abkürzungen [in Python] zum Verweisen auf die Mitglieder des Objekts aus seinen Methoden: Die Methodenfunktion wird mit einem expliziten ersten Argument deklariert, das das Objekt darstellt und implizit durch den Aufruf bereitgestellt wird.

Oft heißt das erste Argument einer Methode self. Dies ist nichts weiter als eine Konvention: Der Name self hat für Python absolut keine besondere Bedeutung. Beachten Sie jedoch, dass Ihr Code für andere Python-Programmierer möglicherweise weniger lesbar ist, wenn Sie die Konvention nicht befolgen. Es ist auch denkbar, dass ein Klassenbrowserprogramm geschrieben wird, das auf einer solchen Konvention basiert.

Weitere Informationen finden Sie im Python-Dokumentations-Tutorial zu Klassen .

Matthew Rankin
quelle
20

Neben allen anderen bereits genannten Gründen ermöglicht es einen einfacheren Zugriff auf überschriebene Methoden. Sie können anrufen Class.some_method(inst).

Ein Beispiel dafür, wo es nützlich ist:

class C1(object):
    def __init__(self):
         print "C1 init"

class C2(C1):
    def __init__(self): #overrides C1.__init__
        print "C2 init"
        C1.__init__(self) #but we still want C1 to init the class too
>>> C2()
"C2 init"
"C1 init"
Ponkadoodle
quelle
17

Die Verwendung ähnelt der Verwendung des thisSchlüsselworts in Java, dh um einen Verweis auf das aktuelle Objekt zu geben.

Gaurav Nishant
quelle
2
Klasse myClass: def myFunc (this, name): this.name = name
LEMUEL ADANE
16

Python ist im Gegensatz zu Java oder C ++ keine Sprache für objektorientierte Programmierung.

Wenn man eine statische Methode in Python aufruft, schreibt man einfach eine Methode mit regulären Argumenten.

class Animal():
    def staticMethod():
        print "This is a static method"

Für eine Objektmethode, bei der Sie eine Variable erstellen müssen, bei der es sich in diesem Fall um ein Tier handelt, ist jedoch das Argument self erforderlich

class Animal():
    def objectMethod(self):
        print "This is an object method which needs an instance of a class"

Die self-Methode wird auch verwendet, um auf ein Variablenfeld innerhalb der Klasse zu verweisen.

class Animal():
    #animalName made in constructor
    def Animal(self):
        self.animalName = "";


    def getAnimalName(self):
        return self.animalName

In diesem Fall bezieht sich self auf die Variable animalName der gesamten Klasse. ERINNERN SIE SICH: Wenn Sie eine Variable in einer Methode haben, funktioniert self nicht. Diese Variable ist einfach nur vorhanden, während diese Methode ausgeführt wird. Um Felder (die Variablen der gesamten Klasse) zu definieren, müssen Sie sie AUSSERHALB der Klassenmethoden definieren.

Wenn Sie kein einziges Wort von dem verstehen, was ich sage, dann Google "Objektorientierte Programmierung". Sobald Sie dies verstanden haben, müssen Sie diese Frage nicht einmal mehr stellen :).

ytpillai
quelle
+1 wegen der Unterscheidung zwischen staticMethod()und objectMethod(self). Ich möchte hinzufügen, dass, um die erste aufzurufen, Sie sagen würden Animal.staticMethod(), während objectMethod()eine Instanz benötigt:a = Animal(); a.objectMethod()
Laryx Decidua
Was Sie sagen, ist nicht 100% wahr. Das ist nur eine Konvention. Sie können die statische Methode weiterhin von einem erstellten Objekt aus aufrufen. Sie können einfach keine Klassenmitglieder verwenden, weil Sie kein Selbst deklariert haben. Ich kann sogar Animal.objectMethod (animalObj) aufrufen, um das Nicht-Statische aufzurufen. Grundsätzlich bedeutet dies, dass eine statische Methode nur eine Methode ist, die keine Mitgliedsvariablen verwendet. Es sollte nicht nötig sein, sich selbst zu deklarieren. Es ist eine dumme Sprachanforderung, denke ich. Sprachen wie Lua und C ++ geben Ihnen hinter den Kulissen obj-Variablen.
user441521
Sie haben eine nutzlose animalName-Zeichenfolgendeklaration und eine abstürzende animalName-Methode erstellt.
Cees Timmerman
3
@ytpillai Irrelevant. Verwirrender und falscher Code sollte nicht als Antwort angezeigt werden.
Cees Timmerman
1
def getAnimalNameUm die Zeichenfolge, die Sie zurückgeben möchten, nicht zu beschädigen, selfbezieht sie sich auf die Instanz der Klasse und nicht auf ein Feld darin.
Cees Timmerman
10

Es ist da, um dem Python-Zen zu folgen: "Explizit ist besser als implizit". Es ist in der Tat ein Verweis auf Ihr Klassenobjekt. In Java und PHP heißt es beispielsweise this.

Wenn user_type_namesich in Ihrem Modell ein Feld befindet, greifen Sie über zu self.user_type_name.

dan-klasson
quelle
10

Zuallererst ist Selbst ein herkömmlicher Name, man könnte alles andere (kohärent sein) an seine Stelle setzen.

Es bezieht sich auf das Objekt selbst. Wenn Sie es also verwenden, erklären Sie, dass .name und .age Eigenschaften der Student-Objekte (Hinweis, nicht der Student-Klasse) sind, die Sie erstellen möchten.

class Student:
    #called each time you create a new Student instance
    def __init__(self,name,age): #special method to initialize
        self.name=name
        self.age=age

    def __str__(self): #special method called for example when you use print
        return "Student %s is %s years old" %(self.name,self.age)

    def call(self, msg): #silly example for custom method
        return ("Hey, %s! "+msg) %self.name

#initializing two instances of the student class
bob=Student("Bob",20)
alice=Student("Alice",19)

#using them
print bob.name
print bob.age
print alice #this one only works if you define the __str__ method
print alice.call("Come here!") #notice you don't put a value for self

#you can modify attributes, like when alice ages
alice.age=20
print alice

Code ist hier

Akash Kandpal
quelle
1
Ihre Antwort scheint mir am klarsten zu sein. +1
Pawel
9

selfist eine Objektreferenz auf das Objekt selbst, daher sind sie gleich. Python-Methoden werden nicht im Kontext des Objekts selbst aufgerufen. selfin Python kann verwendet werden, um mit benutzerdefinierten Objektmodellen oder etwas anderem umzugehen.

Ming-Tang
quelle
8

Die Verwendung des Arguments, herkömmlich genannt self ist nicht so schwer zu verstehen, wie auch, warum es notwendig ist? Oder warum es explizit erwähnen? Ich nehme an, das ist eine größere Frage für die meisten Benutzer, die diese Frage nachschlagen, oder wenn dies nicht der Fall ist, werden sie mit Sicherheit die gleiche Frage haben, wenn sie Python lernen. Ich empfehle ihnen, diese paar Blogs zu lesen:

1: Verwendung von selbsterklärten

Beachten Sie, dass es sich nicht um ein Schlüsselwort handelt.

Das erste Argument jeder Klassenmethode, einschließlich init, ist immer ein Verweis auf die aktuelle Instanz der Klasse. Konventionell heißt dieses Argument immer self. In der init-Methode bezieht sich self auf das neu erstellte Objekt. In anderen Klassenmethoden bezieht es sich auf die Instanz, deren Methode aufgerufen wurde. Zum Beispiel ist der folgende Code der gleiche wie der obige Code.

2: Warum haben wir es so und warum können wir es nicht wie Java als Argument entfernen und stattdessen ein Schlüsselwort haben

Eine andere Sache, die ich hinzufügen möchte, ist, selfdass ich mit einem optionalen Argument statische Methoden innerhalb einer Klasse deklarieren kann, indem ich nicht schreibe self.

Codebeispiele:

class MyClass():
    def staticMethod():
        print "This is a static method"

    def objectMethod(self):
        print "This is an object method which needs an instance of a class, and that is what self refers to"

PS : Dies funktioniert nur in Python 3.x.

In früheren Versionen müssen Sie den @staticmethodDekorator explizit hinzufügen , andernfalls ist ein selfArgument obligatorisch.

Bugs Buggy
quelle
7

Ich bin überrascht, dass niemand Lua erzogen hat. Lua verwendet auch die Variable 'self', sie kann jedoch weggelassen, aber weiterhin verwendet werden. C ++ macht dasselbe mit 'this'. Ich sehe keinen Grund, in jeder Funktion 'self' deklarieren zu müssen, aber Sie sollten es trotzdem genauso verwenden können wie mit lua und C ++. Für eine Sprache, die stolz darauf ist, kurz zu sein, ist es seltsam, dass Sie die Selbstvariable deklarieren müssen.

user441521
quelle
6

Schauen Sie sich das folgende Beispiel an, das den Zweck von klar erklärt self

class Restaurant(object):  
    bankrupt = False

    def open_branch(self):
        if not self.bankrupt:
           print("branch opened")

#create instance1
>>> x = Restaurant()
>>> x.bankrupt
False

#create instance2
>>> y = Restaurant()
>>> y.bankrupt = True   
>>> y.bankrupt
True

>>> x.bankrupt
False  

self wird verwendet / benötigt, um zwischen Instanzen zu unterscheiden.

Quelle: Selbstvariable in Python erklärt - Pythontips

kmario23
quelle
Ja, ich denke, wir wissen, warum Selbst verwendet wird, aber die Frage ist, warum die Sprache Sie dazu bringt, es explizit zu deklarieren. Viele andere Sprachen erfordern dies nicht und eine Sprache, die stolz darauf ist, kurz zu sein. Man könnte meinen, sie würde Ihnen nur die Variable hinter den Kulissen geben, die Sie wie Lua oder C ++ (dies) verwenden können.
user441521
3
@ kmario23 Ihre Antwort war von hier: pythontips.com/2013/08/07/the-self-variable-in-python-explained Bitte bestätigen Sie immer die Originalautoren, wenn Sie Antworten als Ihre eigenen veröffentlichen.
Geekidharsh
@geekidharsh danke, ich habe eine Notiz hinzugefügt!
kmario23
5

Denn weil Python übrigens so gestaltet ist, würden die Alternativen kaum funktionieren. Python wurde entwickelt, um die Definition von Methoden oder Funktionen in einem Kontext zu ermöglichen, in dem sowohl implizite this(a-la Java / C ++) als auch explizite @(a-la Ruby) nicht funktionieren würden. Lassen Sie uns ein Beispiel mit dem expliziten Ansatz mit Python-Konventionen haben:

def fubar(x):
    self.x = x

class C:
    frob = fubar

Jetzt würde die fubarFunktion nicht funktionieren, da davon ausgegangen wird, dass selfes sich um eine globale Variable handelt (und auch in frob). Die Alternative wäre, Methoden mit einem ersetzten globalen Bereich auszuführen (wobeiself ist das Objekt).

Der implizite Ansatz wäre

def fubar(x)
    myX = x

class C:
    frob = fubar

Dies würde bedeuten, dass myXdies als lokale Variable in fubar(und in) interpretiert wirdfrob ) . Die Alternative wäre hier, Methoden mit einem ersetzten lokalen Bereich auszuführen, der zwischen den Aufrufen beibehalten wird, aber dies würde die Möglichkeit lokaler Methodenvariablen aufheben.

Die aktuelle Situation funktioniert jedoch gut:

 def fubar(self, x)
     self.x = x

 class C:
     frob = fubar

Hier wird beim Aufrufen als Methode frobdas Objekt empfangen, für das es über den selfParameter aufgerufen wird, und es fubarkann weiterhin mit einem Objekt als Parameter aufgerufen werden und funktioniert genauso (es ist dasselbe, wie C.frobich denke).

Himmel König
quelle
3

In der __init__Methode bezieht sich self auf das neu erstellte Objekt. In anderen Klassenmethoden bezieht es sich auf die Instanz, deren Methode aufgerufen wurde.

Selbst als Name ist nur eine Konvention , nennen Sie es wie Sie wollen! Wenn Sie es jedoch verwenden, um beispielsweise das Objekt zu löschen, müssen Sie denselben Namen verwenden : __del__(var), wo varin der__init__(var,[...])

Sie sollten auch einen Blick darauf werfen cls, um das Gesamtbild zu erhalten . Dieser Beitrag könnte hilfreich sein.

Oussama L.
quelle
3

self verhält sich wie der aktuelle Objektname oder die Instanz der Klasse.

# Self explanation.


 class classname(object):

    def __init__(self,name):

        self.name=name
        # Self is acting as a replacement of object name.
        #self.name=object1.name

   def display(self):
      print("Name of the person is :",self.name)
      print("object name:",object1.name)


 object1=classname("Bucky")
 object2=classname("ford")

 object1.display()
 object2.display()

###### Output 
Name of the person is : Bucky
object name: Bucky
Name of the person is : ford
object name: Bucky
sameer_nubia
quelle
1

self ist unvermeidbar.

Es war nur eine Frage sollte selfimplizit oder explizit sein. Guido van Rossumlöste diese Frage zu sagen, selfmuss bleiben .

Also wo selfleben die?

Wenn wir uns nur an die funktionale Programmierung halten würden, würden wir sie nicht brauchen self. Sobald wir die Python-OOP betreten , finden wirself dort.

Hier ist der typische Anwendungsfall class Cmit der Methodem1

class C:
    def m1(self, arg):
        print(self, ' inside')
        pass

ci =C()
print(ci, ' outside')
ci.m1(None)
print(hex(id(ci))) # hex memory address

Dieses Programm gibt Folgendes aus:

<__main__.C object at 0x000002B9D79C6CC0>  outside
<__main__.C object at 0x000002B9D79C6CC0>  inside
0x2b9d79c6cc0

So selfhält die Speicheradresse des Klasseninstanz. Der Zweck von selfwäre, die Referenz für beispielsweise Methoden zu halten und expliziten Zugriff auf diese Referenz zu haben.


Beachten Sie, dass es drei verschiedene Arten von Klassenmethoden gibt:

  • statische Methoden (sprich: Funktionen),
  • Klassenmethoden,
  • Instanzmethoden (erwähnt).
Prosti
quelle
0

aus den Dokumenten ,

Das Besondere an Methoden ist, dass das Instanzobjekt als erstes Argument der Funktion übergeben wird. In unserem Beispiel entspricht der Aufruf x.f()genau MyClass.f(x). Im Allgemeinen entspricht das Aufrufen einer Methode mit einer Liste von n Argumenten dem Aufrufen der entsprechenden Funktion mit einer Argumentliste, die durch Einfügen des Instanzobjekts der Methode vor dem ersten Argument erstellt wird.

davor das zugehörige Snippet,

class MyClass:
    """A simple example class"""
    i = 12345

    def f(self):
        return 'hello world'

x = MyClass()

nmxl
quelle
-2

Es ist ein expliziter Verweis auf das Klasseninstanzobjekt.

SilentGhost
quelle
21
Ich glaube nicht, dass dies Richzilla hilft, den Grund dafür zu verstehen.
Georg Schölly
1
@ SilentGhost: Du hast es geschafft. Ich bin beeindruckt. Wenn ich es richtig verstehe: Ich erstelle ein Objekt als Instanz der definierten Klasse und der Parameter self verweist auf dieses Objekt? Ich verstehe, dass sich Selbst implizit auf die Klasse selbst bezieht, aber es wäre großartig, wenn Sie Ihre Antwort etwas genauer erklären würden.
dkrynicki