Was machen __init__ und self auf Python?

792

Ich lerne die Programmiersprache Python und bin auf etwas gestoßen, das ich nicht vollständig verstehe.

In einer Methode wie:

def method(self, blah):
    def __init__(?):
        ....
    ....

Was macht selfdas Was soll es sein? Ist es obligatorisch?

Was macht die __init__Methode? Warum ist es notwendig? (usw.)

Ich denke, es könnten OOP-Konstrukte sein, aber ich weiß nicht viel.

ivanleoncz
quelle

Antworten:

585

In diesem Code:

class A(object):
    def __init__(self):
        self.x = 'Hello'

    def method_a(self, foo):
        print self.x + ' ' + foo

... die selfVariable repräsentiert die Instanz des Objekts selbst. Die meisten objektorientierten Sprachen übergeben dies als versteckten Parameter an die für ein Objekt definierten Methoden. Python nicht. Sie müssen es explizit deklarieren. Wenn Sie eine Instanz der AKlasse erstellen und ihre Methoden aufrufen, wird sie automatisch übergeben, wie in ...

a = A()               # We do not pass any argument to the __init__ method
a.method_a('Sailor!') # We only pass a single argument

Die __init__Methode entspricht in etwa einem Konstruktor in Python. Wenn Sie A()Python aufrufen, wird ein Objekt für Sie erstellt und als erster Parameter an die __init__Methode übergeben. Alle zusätzlichen Parameter (z. B. A(24, 'Hello')) werden ebenfalls als Argumente übergeben. In diesem Fall wird eine Ausnahme ausgelöst, da der Konstruktor sie nicht erwartet.

Chris B.
quelle
8
Was ist, wenn Sie x = 'Hello'außerhalb von init, aber innerhalb der Klasse setzen? Ist es wie Java, wo es dasselbe ist, oder wird es wie eine statische Variable, die nur einmal initialisiert wird?
Jayen
15
Es ist wie eine statische Variable. Es wird nur einmal initialisiert und ist über A.xoder verfügbar a.x. Beachten Sie, dass das Überschreiben einer bestimmten Klasse keine Auswirkungen auf die Basis hat. A.x = 'foo'; a.x = 'bar'; print a.x; print A.xDrucken Sie bardannfoo
Chris B.
156
Es sei darauf hingewiesen, dass das erste Argument nicht unbedingt genannt werden muss self, sondern nur durch Konvention.
Henry Gomersall
13
Was bringt objectdie Klassendeklaration? Ich habe bemerkt, dass einige Klassen dies haben und andere nicht
Chris
9
@ Chris Es ist für Python 2-Kompatibilität. In Python 3 muss nicht explizit geerbt werden, objectda dies standardmäßig geschieht.
Gabriel
241

Ja, Sie haben Recht, das sind oop Konstrukte.

__init__ist der Konstruktor für eine Klasse. Der selfParameter bezieht sich auf die Instanz des Objekts (wie thisin C ++).

class Point:
    def __init__(self, x, y):
        self._x = x
        self._y = y

Die __init__Methode wird aufgerufen, wenn Speicher für das Objekt zugewiesen wird:

x = Point(1,2)

Es ist wichtig, den selfParameter in der Methode eines Objekts zu verwenden, wenn Sie den Wert für das Objekt beibehalten möchten. Wenn Sie die __init__Methode beispielsweise folgendermaßen implementieren :

class Point:
    def __init__(self, x, y):
        _x = x
        _y = y

Ihre xund yParameter werden in Variablen auf dem Stapel gespeichert und verworfen, wenn die init-Methode den Gültigkeitsbereich verlässt. Festlegen dieser Variablen als self._xund Festlegen dieser Variablen als self._yMitglieder des PointObjekts (Zugriff für die Lebensdauer des Objekts).

RedBlueThing
quelle
1
Gibt es also einen Grund, warum Sie nicht selfim Konstruktor sein möchten ? Warum müssen Sie es überhaupt angeben, wäre es nicht besser, wenn es implizit wäre?
Aaron Franke
Soweit ich weiß, ist __ init __ kein Konstruktor, sondern die erste Methode, die ausgeführt wird, wenn ein Objekt erstellt wird. __ init __ wird zum Einrichten des Objekts verwendet. __ new __ ist der Konstruktor in Python.
Deepanshu
206

Ein kurzes anschauliches Beispiel

In der Hoffnung, dass es ein wenig helfen könnte, hier ein einfaches Beispiel, mit dem ich den Unterschied zwischen einer in einer Klasse deklarierten Variablen und einer in einer __init__Funktion deklarierten Variablen verstanden habe :

class MyClass(object):
    i = 123
    def __init__(self):
        self.i = 345

a = MyClass()
print(a.i)
print(MyClass.i)

Ausgabe:

345
123
Dave Everitt
quelle
7
Interessante Beobachtung, aber ich denke, Sie sind auf dem falschen Weg. Mit print MyClass.i sieht es eher so aus, als würden Sie eine 'statische' Variable i aufrufen. Wo Sie wie bei ai eine Mitgliedsvariable aufrufen, d.h. Es scheint mir, dass init nur ein Konstruktor ist, der zuerst ausgeführt wird, wenn Sie ein Objekt der Klasse erstellen.
Captainspi
34
Das habe ich versucht, mir mit diesem Beispiel zu erklären - dass die von festgelegte Variable __init__an Instanzen der Klasse übergeben wird, nicht an die 'statische' Variable der Klasse selbst, die denselben Namen hat ...
Dave Everitt
44

Zusamenfassend:

  1. selfbezieht sich, wie es nahelegt, auf sich selbst - das Objekt, das die Methode aufgerufen hat. Das heißt, wenn Sie N Objekte haben, die die Methode aufrufen, self.averweist dies für jedes der N Objekte auf eine separate Instanz der Variablen. Stellen Sie sich N Kopien der Variablen afür jedes Objekt vor
  2. __init__wird in anderen OOP-Sprachen wie C ++ / Java als Konstruktor bezeichnet. Die Grundidee ist, dass es sich um eine spezielle Methode handelt, die automatisch aufgerufen wird, wenn ein Objekt dieser Klasse erstellt wird
Scharfsinn
quelle
29

__init__verhält sich wie ein Konstruktor. Sie müssen "self" als erstes Argument an alle Klassenfunktionen übergeben, wenn Sie möchten, dass sie sich als nicht statische Methoden verhalten. "self" sind Instanzvariablen für Ihre Klasse.

ewalk
quelle
1
'self' definiert, ob eine Methode statisch ist oder nicht! Wow, das ist ein Augenöffner für diesen Java-Typen.
Liwevire
25

Probieren Sie diesen Code aus. Ich hoffe, es hilft vielen C-Programmierern wie mir, Py zu lernen.

#! /usr/bin/python2

class Person:

    '''Doc - Inside Class '''

    def __init__(self, name):
        '''Doc - __init__ Constructor'''
        self.n_name = name        

    def show(self, n1, n2):
        '''Doc - Inside Show'''
        print self.n_name
        print 'Sum = ', (n1 + n2)

    def __del__(self):
        print 'Destructor Deleting object - ', self.n_name

p=Person('Jay')
p.show(2, 3)
print p.__doc__
print p.__init__.__doc__
print p.show.__doc__

Ausgabe:

Jay

Sum = 5

Doc - Inside Class

Doc - __init__ Constructor

Doc - Inside Show

Destructor Deleting object - Jay

Jayzcode
quelle
Ich weiß nicht, ob es nur ich ist, aber das Lesen dieses Codes war etwas verwirrend. Vielleicht liegt es daran, dass ich noch ein Anfänger in Python bin, idk.
Linny
Ich bin mir nicht sicher über die Doc- Sache. Zieht es die Dokumentation? und wenn ich Folgendes mache: '' 'test - my doc' '', kann ich Folgendes verwenden: print.p .__ test__? oder ist doc ein bestimmtes Schlüsselwort?
Thomas
@Thomas doc ist das Schlüsselwort für dokumentierte Details. Dreifache Anführungszeichen werden zum Aufschreiben von Dokumenten verwendet, und das Dokument ist eine optionale Entität.
Jayzcode
24

Klassenobjekte unterstützen zwei Arten von Operationen: Attributreferenzen und Instanziierung

Attributreferenzen verwenden die Standardsyntax, die für alle Attributreferenzen in Python verwendet wird: obj.name. Gültige Attributnamen sind alle Namen, die sich beim Erstellen des Klassenobjekts im Namespace der Klasse befanden. Wenn also die Klassendefinition so aussah:

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

    def f(self):
        return 'hello world'

dann MyClass.iund MyClass.fsind gültige Attributreferenzen, die eine Ganzzahl bzw. ein Funktionsobjekt zurückgeben. Klassenattribute können auch zugewiesen werden, sodass Sie den Wert von MyClass.idurch Zuweisung ändern können . __doc__ist auch ein gültiges Attribut, das den zur Klasse gehörenden Dokumentstring zurückgibt: "Eine einfache Beispielklasse".

Die Klasseninstanziierung verwendet die Funktionsnotation. Stellen Sie sich einfach vor, das Klassenobjekt sei eine parameterlose Funktion, die eine neue Instanz der Klasse zurückgibt. Zum Beispiel:

x = MyClass()

Die Instanziierungsoperation ("Aufrufen" eines Klassenobjekts) erstellt ein leeres Objekt. Viele Klassen erstellen gerne Objekte mit Instanzen, die an einen bestimmten Anfangszustand angepasst sind. Daher kann eine Klasse eine spezielle Methode mit folgendem Namen definieren __init__():

def __init__(self):
    self.data = []

Wenn eine Klasse eine __init__()Methode definiert , wird die Klasseninstanziierung automatisch __init__()für die neu erstellte Klasseninstanz aufgerufen. In diesem Beispiel kann eine neue, initialisierte Instanz erhalten werden durch:

x = MyClass()

Natürlich kann die __init__()Methode Argumente für eine größere Flexibilität haben. In diesem Fall werden Argumente, die dem Klasseninstanziierungsoperator gegeben wurden, an weitergeleitet __init__(). Zum Beispiel,

class Complex:
    def __init__(self, realpart, imagpart):
        self.r = realpart
        self.i = imagpart

x = Complex(3.0, -4.5)
x.r, x.i

Entnommen aus offiziellen Unterlagen, die mir am Ende am meisten geholfen haben.


Hier ist mein Beispiel

class Bill():
    def __init__(self,apples,figs,dates):
        self.apples = apples
        self.figs = figs
        self.dates = dates
        self.bill = apples + figs + dates
        print ("Buy",self.apples,"apples", self.figs,"figs 
                and",self.dates,"dates. 
                Total fruitty bill is",self.bill," pieces of fruit :)")

Wenn Sie eine Instanz der Klasse Bill erstellen:

purchase = Bill(5,6,7)

Du erhältst:

> Buy 5 apples 6 figs and 7 dates. Total fruitty bill is 18  pieces of
> fruit :)
Harvey
quelle
22

Hatte Probleme, das selbst zu verstehen. Auch nach dem Lesen der Antworten hier.

Um die __init__Methode richtig zu verstehen , müssen Sie sich selbst verstehen.

Der Selbstparameter

Die von der __init__Methode akzeptierten Argumente sind:

def __init__(self, arg1, arg2):

Aber wir geben nur zwei Argumente an:

instance = OurClass('arg1', 'arg2')

Woher kommt das zusätzliche Argument?

Wenn wir auf Attribute eines Objekts zugreifen, geschieht dies nach Name (oder Referenz). Hier ist die Instanz ein Verweis auf unser neues Objekt. Wir greifen mit instance.printargs auf die printargs-Methode des Instanzobjekts zu.

Um innerhalb der __init__Methode auf Objektattribute zugreifen zu können, benötigen wir einen Verweis auf das Objekt.

Bei jedem Aufruf einer Methode wird als erstes Argument ein Verweis auf das Hauptobjekt übergeben. Konventionell nennen Sie dieses erste Argument immer Ihre Methoden selbst.

Dies bedeutet in der __init__Methode, die wir tun können:

self.arg1 = arg1
self.arg2 = arg2

Hier setzen wir Attribute für das Objekt. Sie können dies überprüfen, indem Sie folgende Schritte ausführen:

instance = OurClass('arg1', 'arg2')
print instance.arg1
arg1

Werte wie diese werden als Objektattribute bezeichnet. Hier __init__legt die Methode die Attribute arg1 und arg2 der Instanz fest.

Quelle: http://www.voidspace.org.uk/python/articles/OOP.shtml#the-init-method

eee
quelle
17

Beachten Sie, dass selfdies tatsächlich eine gültige Python-ID sein kann. Zum Beispiel könnten wir genauso gut aus Chris Bs Beispiel schreiben:

class A(object):
    def __init__(foo):
        foo.x = 'Hello'

    def method_a(bar, foo):
        print bar.x + ' ' + foo

und es würde genauso funktionieren. Es wird jedoch empfohlen, self zu verwenden, da andere Python-Benutzer dies leichter erkennen.

SingleNegationElimination
quelle
Ich bin damit einverstanden, dass selbst anstelle von foo empfohlen wird, hilft anderen Programmierern beim Betrachten des Codes
Linny
15

Grundsätzlich müssen Sie das Schlüsselwort 'self' verwenden, wenn Sie eine Variable in mehreren Funktionen innerhalb derselben Klasse verwenden. Wie für init , wird es auf Standardwerte des Setup incase keine anderen Funktionen innerhalb dieser Klasse verwendet werden , genannt.

user1675111
quelle
6
In Python gibt es kein "self" -Schlüsselwort. Das Aufrufen des ersten Parameters 'self' ist einfach eine Konvention.
David Anderson
self wird grundsätzlich als Platzhalter verwendet. Es ist nicht erforderlich, dass Sie sich selbst verwenden, Sie könnten "eeee" oder "foo" oder etwas anderes verwenden, es wird nur anderen Programmierern empfohlen, während Sie Ihren Code lesen
Linny
15
  1. __init__ist im Grunde eine Funktion, die die Eigenschaften der Klasse für ein bestimmtes Objekt "initialisiert" / "aktiviert" , sobald sie erstellt und mit der entsprechenden Klasse abgeglichen wurde.
  2. self stellt das Objekt dar, das diese Eigenschaften erbt.
Atlas
quelle
1
Das Schlüsselwort "self" muss nicht verwendet werden, es ist nur ein Platzhalter. Sie können jedes Wort verwenden, aber es wird empfohlen, dass Sie sich selbst verwenden, um die Lesbarkeit des Programms zu
verbessern
13

Das 'Selbst' ist eine Referenz auf die Klasseninstanz

class foo:
    def bar(self):
            print "hi"

Jetzt können wir eine Instanz von foo erstellen und die Methode darauf aufrufen. In diesem Fall wird der Parameter self von Python hinzugefügt:

f = foo()
f.bar()

Es kann aber auch übergeben werden, wenn der Methodenaufruf nicht im Kontext einer Instanz der Klasse steht. Der folgende Code macht dasselbe

f = foo()
foo.bar(f)

Interessanterweise ist der Variablenname 'self' nur eine Konvention. Der folgende Definition wird funktionieren genau die gleiche .. Having said , dass es sehr starke Konvention , die befolgt werden soll , immer , aber es sagt etwas über flexible Art der Sprache

class foo:
    def bar(s):
            print "hi"
Tarn
quelle
Warum sagt das etwas über die Flexibilität der Sprache aus? Es heißt nur, dass Sie Variablen einen beliebigen legalen Namen geben können. Wie unterscheidet sich das von jeder anderen Programmiersprache?
Daniel
Wie ich in meiner Antwort geschrieben habe, ist "bar" nur eine Funktion, bei der eine Klasseninstanz als erster Parameter bereitgestellt wird. Während "bar" als eine an "foo" gebundene Methode definiert ist, kann sie auch mit einer Instanz einer anderen Klasse aufgerufen werden. So funktionieren Methoden und "dies" beispielsweise in Java nicht, obwohl ich mir vorstelle, dass dies das gleiche Konzept, die gleichen Funktionen und der gleiche Instanzkontext sind (der Instanzkontext ist der erste Parameter in Python und "dies" in Java "). Vielleicht können Sie jetzt die Flexibilität der Sprache sehen, auf die ich mich bezog?
Tarn
Ja, das zeigt die Flexibilität der Sprache. So wie Sie Ihre Antwort formuliert haben, schien es, als würden Sie sagen, dass die Tatsache, dass Sie die Variable "self" als etwas anderes (wie s) bezeichnen könnten , die Flexibilität von Python zeigt.
Daniel
12

Nur eine Demo für die Frage.

class MyClass:

    def __init__(self):
        print('__init__ is the constructor for a class')

    def __del__(self):
        print('__del__ is the destructor for a class')

    def __enter__(self):
        print('__enter__ is for context manager')
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print('__exit__ is for context manager')

    def greeting(self):
        print('hello python')


if __name__ == '__main__':
    with MyClass() as mycls:
        mycls.greeting()

$ python3 class.objects_instantiation.py
__init__ is the constructor for a class
__enter__ is for context manager
hello python
__exit__ is for context manager
__del__ is the destructor for a class
debuggen
quelle
11

In diesem Code:

class Cat:
    def __init__(self, name):
        self.name = name
    def info(self):
        print 'I am a cat and I am called', self.name

Hier __init__fungiert er als Konstruktor für die Klasse, und wenn ein Objekt instanziiert wird, wird diese Funktion aufgerufen. selfrepräsentiert das instanziierende Objekt.

c = Cat('Kitty')
c.info()

Das Ergebnis der obigen Aussagen ist wie folgt:

I am a cat and I am called Kitty
Anagha
quelle
11

Was macht das Selbst ? Was ist das gemeint sein? Ist es obligatorisch ?

Das erste Argument jeder Klassenmethode, einschließlich init, ist immer ein Verweis auf die aktuelle Instanz der Klasse . Konventionell wird dieses Argument immer benannt self. selfBezieht sich in der init-Methode auf das neu erstellte Objekt. In anderen Klassenmethoden bezieht es sich auf die Instanz, deren Methode aufgerufen wurde.

Python zwingt Sie nicht dazu, " self " zu verwenden. Sie können ihm einen beliebigen Namen geben. Denken Sie jedoch daran, dass das erste Argument in einer Methodendefinition eine Referenz auf das Objekt ist . Python fügt das selfArgument der Liste für Sie hinzu. Sie müssen es nicht einschließen, wenn Sie die Methoden aufrufen. Wenn Sie in der init-Methode nicht self angegeben haben, wird eine Fehlermeldung angezeigt

TypeError: __init___() takes no arguments (1 given)

Was macht die init- Methode? Warum ist es notwendig? (usw.)

initsteht für Initialisierung. Es ist ein Konstruktor, der aufgerufen wird, wenn Sie eine Instanz der Klasse erstellen, und der nicht erforderlich ist . Normalerweise ist es jedoch unsere Praxis, eine init-Methode zum Festlegen des Standardstatus des Objekts zu schreiben. Wenn Sie zunächst keinen Status des Objekts festlegen möchten, müssen Sie diese Methode nicht schreiben.

Muhammad Faizan Khan
quelle
8
# Source: Class and Instance Variables
# https://docs.python.org/2/tutorial/classes.html#class-and-instance-variables

class MyClass(object):
    # class variable
    my_CLS_var = 10

    # sets "init'ial" state to objects/instances, use self argument
    def __init__(self):
        # self usage => instance variable (per object)
        self.my_OBJ_var = 15

        # also possible, class name is used => init class variable
        MyClass.my_CLS_var = 20


def run_example_func():
    # PRINTS    10    (class variable)
    print MyClass.my_CLS_var

    # executes __init__ for obj1 instance
    # NOTE: __init__ changes class variable above
    obj1 = MyClass()

    # PRINTS    15    (instance variable)
    print obj1.my_OBJ_var

    # PRINTS    20    (class variable, changed value)
    print MyClass.my_CLS_var


run_example_func()
Manohar Reddy Poreddy
quelle
5

Python __init__und selfwas machen sie?

Was macht selfdas Was soll es sein? Ist es obligatorisch?

Was macht die __init__Methode? Warum ist es notwendig? (usw.)

Das angegebene Beispiel ist nicht korrekt. Lassen Sie mich darauf basierend ein korrektes Beispiel erstellen:

class SomeObject(object):

    def __init__(self, blah):
        self.blah = blah

    def method(self):
        return self.blah 

Wenn wir eine Instanz des Objekts erstellen, wird das __init__aufgerufen, um das Objekt nach seiner Erstellung anzupassen. Das heißt, wenn wir SomeObjectmit 'blah'unten aufrufen (was alles sein könnte), wird es __init__als Argument an die Funktion übergeben blah:

an_object = SomeObject('blah')

Das selfArgument ist die Instanz SomeObject, der zugewiesen wird an_object.

Später möchten wir möglicherweise eine Methode für dieses Objekt aufrufen:

an_object.method()

Durch die gepunktete Suche wird an_object.methoddie Instanz an eine Instanz der Funktion gebunden, und die Methode (wie oben aufgerufen) ist jetzt eine "gebundene" Methode. Dies bedeutet, dass wir die Instanz nicht explizit an den Methodenaufruf übergeben müssen .

Der Methodenaufruf ruft die Instanz ab, weil sie an die gepunktete Suche gebunden war, und führt beim Aufruf den Code aus, für den sie programmiert wurde.

Das implizit übergebene selfArgument wird selfdurch Konvention aufgerufen . Wir könnten jeden anderen legalen Python-Namen verwenden, aber Sie werden wahrscheinlich von anderen Python-Programmierern geteert und gefiedert, wenn Sie ihn in etwas anderes ändern.

__init__ist eine spezielle Methode, die in der Dokumentation zum Python-Datenmodell dokumentiert ist . Es wird unmittelbar nach dem Erstellen der Instanz aufgerufen (normalerweise über __new__- obwohl dies __new__nur erforderlich ist, wenn Sie einen unveränderlichen Datentyp unterklassifizieren).

Aaron Hall
quelle
3

Hier hat der Typ ziemlich gut und einfach geschrieben: https://www.jeffknupp.com/blog/2014/06/18/improve-your-python-python-classes-and-object-oriented-programming/

Lesen Sie den obigen Link als Hinweis darauf:

self? Was ist mit diesem Selbstparameter für alle Kundenmethoden? Was ist es? Natürlich ist es die Instanz! Anders ausgedrückt, eine Methode wie das Abheben definiert die Anweisungen zum Abheben von Geld von einem abstrakten Kundenkonto. Durch Aufrufen von jeff.withdraw (100.0) werden diese Anweisungen für die jeff-Instanz verwendet.

Wenn wir also def abheben (Selbst, Betrag) sagen, sagen wir: "So ziehen Sie Geld von einem Kundenobjekt (das wir selbst nennen) und einer Dollarzahl (die wir Betrag nennen). Selbst ab ist die Instanz des Kunden, auf die zurückgezogen wird. Ich mache auch keine Analogien. jeff.withdraw (100.0) ist nur eine Abkürzung für Customer.withdraw (jeff, 100.0), die vollkommen gültig ist (wenn nicht oft gesehen). Code.

init self mag für andere Methoden sinnvoll sein, aber was ist mit init ? Wenn wir init aufrufen , sind wir dabei, ein Objekt zu erstellen. Wie kann es also bereits ein Selbst geben? Mit Python können wir das Selbstmuster auch dann erweitern, wenn Objekte erstellt werden, obwohl es nicht genau passt. Stellen Sie sich vor, jeff = Kunde ('Jeff Knupp', 1000.0) ist dasselbe wie jeff = Kunde (jeff, 'Jeff Knupp', 1000.0); Der übergebene Jeff ist auch das Ergebnis.

Aus diesem Grund initialisieren wir beim Aufruf von init Objekte, indem wir Dinge wie self.name = name sagen. Denken Sie daran, da self die Instanz ist, entspricht dies der Aussage von jeff.name = name, was mit jeff.name = 'Jeff Knupp identisch ist. In ähnlicher Weise ist self.balance = balance dasselbe wie jeff.balance = 1000.0. Nach diesen beiden Zeilen betrachten wir das Kundenobjekt als "initialisiert" und einsatzbereit.

Sei vorsichtig was du __init__

Nach Abschluss von init kann der Aufrufer zu Recht davon ausgehen, dass das Objekt einsatzbereit ist. Das heißt, nach jeff = Kunde ('Jeff Knupp', 1000.0) können wir mit der Einzahlung beginnen und Anrufe bei jeff abheben. jeff ist ein vollständig initialisiertes Objekt.

Laxmikant
quelle