it-swarm.com.de

Was ist der Zweck des Wortes "Selbst" in Python?

Was ist der Zweck des Wortes self 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 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

Das verstehe ich ganz leicht. In Python muss jedoch self enthalten sein:

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.

1028
richzilla

Der Grund, warum Sie self. verwenden müssen, ist, dass Python nicht die @ -Syntax verwendet, um auf Instanzattribute zu verweisen. Python hat beschlossen, Methoden so auszuführen, dass die Instanz, zu der die Methode gehört, übergeben automatisch, aber nicht empfangen automatisch: der erste Parameter von Methods ist die Instanz, auf der die Methode aufgerufen wird. Das macht Methoden genauso wie Funktionen und überlässt es Ihnen, den tatsächlichen Namen zu verwenden (obwohl self die Konvention ist und die Leute Sie im Allgemeinen missbilligen, wenn Sie etwas anderes verwenden.) self ist Der Code ist nichts Besonderes, er ist nur ein weiteres Objekt.

Python hätte etwas anderes tun können, um normale Namen von Attributen zu unterscheiden - spezielle Syntax wie Ruby oder erforderliche Deklarationen wie C++ und Java oder vielleicht noch etwas anderes - aber es hat nicht geklappt. Python ist alles dafür da, Dinge explizit zu machen, klar zu machen, was was ist, und obwohl es nicht überall funktioniert, funktioniert es zum Beispiel mit Attributen. Aus diesem Grund muss beim Zuweisen zu einem Instanzattribut bekannt sein, welcher Instanz es zugewiesen werden soll, und aus diesem Grund muss self. angegeben werden.

662
Thomas Wouters

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?

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 davon ausgehen, dass wir keine length -Methode für unsere Vector -Klasse geschrieben haben, können wir Folgendes 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 self -Parameter in length_new wiederverwendet werden kann. Dies wäre ohne ein explizites self nicht möglich.


Eine andere Möglichkeit, die Notwendigkeit des expliziten self zu verstehen, besteht darin, zu sehen, wo Python syntaktischen Zucker hinzufügt. Wenn man bedenkt, ist das im Grunde ein Anruf wie

v_instance.length()

wird intern umgewandelt in

Vector.length(v_instance)

es ist leicht zu erkennen, wo das self hineinpasst. Sie schreiben tatsächlich keine Instanzmethoden in Python; Sie schreiben Klassenmethoden, die eine Instanz als ersten Parameter verwenden müssen. Daher müssen Sie den Instanzparameter explizit an einer beliebigen Stelle platzieren.

406
Debilski

Angenommen, Sie haben eine Klasse ClassA, die eine Methode methodA enthält, die wie folgt definiert ist:

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

und ObjectA ist eine Instanz dieser Klasse.

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

ClassA.methodA(ObjectA, arg1, arg2)

Die Variable self verweist auf das Objekt selbst.

353

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

enter image description here

Aus diesem Grund sind die Daten des Objekts an das Objekt gebunden. Nachfolgend finden Sie ein Beispiel dafür, wie Sie sich vorstellen können, wie die Daten eines Objekts aussehen könnten. Beachten Sie, wie "self" durch den Objektnamen ersetzt wird. Ich sage nicht, dass dieses Beispieldiagramm ganz genau ist, aber es soll hoffentlich dazu dienen, den Gebrauch von sich selbst zu visualisieren.

enter image description here

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

Auch wenn dies möglicherweise nicht ganz korrekt ist, denken Sie an den Vorgang der Instanziierung eines Objekts wie folgt: Wenn ein Objekt erstellt wird, verwendet es die Klasse als Vorlage für seine eigenen Daten und Methoden. Ohne die Übergabe eines eigenen Namens an den Parameter self bleiben die Attribute und Methoden in der Klasse als allgemeine Vorlage erhalten und werden nicht auf das Objekt referenziert (gehören zum Objekt). Durch die Übergabe des Objektnamens an den Parameter self bedeutet dies, dass 100 Objekte, die aus einer Klasse instanziiert wurden, alle ihre eigenen Daten und Methoden verfolgen können.

Siehe die Abbildung unten:

enter image description here

197
sw123456

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: []
74
kame

Ich werde mit Code demonstrieren, dass 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 ein Weg, um zu vermeiden, dass diese "Zustands" -Dinge ständig weitergegeben werden (und andere nette Dinge wie Initialisierung, Klassenzusammenstellung, die selten benötigten Metaklassen und die Unterstützung benutzerdefinierter Methoden zum Überschreiben von Operatoren).

Lassen Sie uns nun den obigen Code unter Verwendung der eingebauten Maschinerie der Klasse python demonstrieren, um zu zeigen, wie es im Grunde genommen 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 )

[migrierte meine Antwort von doppelter geschlossener Frage]

36
ninjagecko

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

Wie in Modula-3 gibt es keine Abkürzungen [in Python], um die Elemente des Objekts aus seinen Methoden zu referenzieren: Die Methodenfunktion wird mit einem expliziten ersten Argument deklariert, das das Objekt darstellt, das implizit vom 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 möglicherweise für andere Python - Programmierer weniger lesbar ist. Es ist auch denkbar, dass ein Klassenbrowser-Programm geschrieben wird, das auf einer solchen Konvention basiert.

Weitere Informationen finden Sie im Tutorial zur Python-Dokumentation für Klassen .

18
Matthew Rankin

Wie alle anderen bereits genannten Gründe ermöglicht es den einfacheren Zugriff auf überschriebene Methoden. Sie können Class.some_method(inst) aufrufen.

Ein Beispiel, 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"
18
Ponkadoodle

Seine Verwendung ähnelt der Verwendung des Schlüsselworts this in Java, d. H. Um einen Verweis auf das aktuelle Objekt zu geben.

14
Gaurav Nishant

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, für die Sie eine Variable erstellen müssen, die in diesem Fall ein Tier ist, 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 Methode self wird auch verwendet, um auf ein variables Feld 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 verweist self auf die Variable animalName der gesamten Klasse. HINWEIS: 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 diese AUSSERHALB der Klassenmethoden definieren.

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

12
ytpillai

Es folgt dem Python Zen "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_name ein Feld in Ihrem Modell ist, greifen Sie mit self.user_type_name darauf zu.

8
dan-klasson

Zuallererst ist Selbst ein konventioneller Name, man könnte alles andere (zusammenhängende) 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 zu erstellenden Student-Objekte (Anmerkung, nicht der Student-Klasse) sind.

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

6
Akash Kandpal

self ist eine Objektreferenz auf das Objekt selbst, daher sind sie gleich. Python -Methoden werden nicht im Kontext des Objekts selbst aufgerufen. self in Python kann verwendet werden, um mit benutzerdefinierten Objektmodellen oder Ähnlichem umzugehen.

6
Ming-Tang

Die Verwendung des Arguments, das herkömmlicherweise self genannt wird, ist nicht so schwer zu verstehen, wie es ist, warum es notwendig ist? Oder warum es ausdrücklich 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 selbst erklärt

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

Das erste Argument jeder Klassenmethode, einschließlich init, verweist immer auf die aktuelle Instanz der Klasse. Konventionell heißt dieses Argument immer self. In der init-Methode verweist 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 eliminieren und haben stattdessen ein Schlüsselwort

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

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 @staticmethod Decorator explizit hinzufügen, andernfalls ist das Argument self obligatorisch.

5
Bugs Buggy

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

5
user441521

Liegt daran, dass python so konzipiert ist, dass die Alternativen kaum funktionieren würden. Python wurde entwickelt, um das Definieren von Methoden oder Funktionen in einem Kontext zu ermöglichen, in dem implizite this (Java/C++) oder explizite _@_ (Ruby) nicht funktionieren. Lassen Sie uns ein Beispiel mit dem expliziten Ansatz mit den Konventionen python geben:

_def fubar(x):
    self.x = x

class C:
    frob = fubar
_

Jetzt würde die Funktion fubar nicht funktionieren, da angenommen wird, dass self eine globale Variable ist (und in frob auch). Die Alternative wäre, Methoden mit einem ersetzten globalen Gültigkeitsbereich auszuführen (wobei self das Objekt ist).

Der implizite Ansatz wäre

_def fubar(x)
    myX = x

class C:
    frob = fubar
_

Dies würde bedeuten, dass myX als lokale Variable in fubar (und auch in frob) interpretiert wird. Die Alternative wäre hier, Methoden mit einem ersetzten lokalen Gültigkeitsbereich auszuführen, der zwischen den Aufrufen beibehalten wird, aber die Möglichkeit lokaler Methodenvariablen aufhebt.

Die derzeitige Situation funktioniert jedoch gut:

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

 class C:
     frob = fubar
_

hier wird beim Aufruf als Methode frob das Objekt empfangen, für das es über den Parameter self aufgerufen wurde, und fubar kann weiterhin mit einem Objekt als Parameter aufgerufen werden und funktioniert wie __ (es ist dasselbe wie _C.frob_ Ich denke).

4
skyking

Schauen Sie sich das folgende Beispiel an, das den Zweck von self klar erläutert.

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.

4
kmario23

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

self ist als Name 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), wobei var in __init__(var,[...]) verwendet wurde.

Sie sollten sich auch cls ansehen, um das größere Bild zu erhalten. Dieser Beitrag könnte hilfreich sein.

2
TheEnglishMe

self ist unvermeidlich.

Es gab nur ein Frage sollte self implizit oder explizit sein. Guido van Rossum löste diese Frage und sagte self muss bleiben .

Wo also leben die self?

Wenn wir uns nur an die funktionale Programmierung halten würden, bräuchten wir self nicht. Sobald wir das Python OOP betreten, finden wir dort self.

Hier ist der typische Anwendungsfall _class C_ mit der Methode _m1_

_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 aus:

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

self enthält also die Speicheradresse der Klasseninstanz. Der Zweck von self wäre, die Referenz für Instanzmethoden zu halten und für uns expliziter Zugriff auf diese Referenz.


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

  • statische Methoden (lies: Funktionen),
  • klassenmethoden,
  • instanzmethoden (erwähnt).
0
prosti