Cosa __init__ e sé fanno su Python?


795

Sto imparando il linguaggio di programmazione Python e mi sono imbattuto in qualcosa che non capisco del tutto.

In un metodo come:

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

Cosa fa self? Cosa significa essere? È obbligatorio?

Cosa fa il __init__metodo? Perché è necessario (eccetera.)

Penso che potrebbero essere costrutti OOP, ma non ne so molto.

Risposte:


585

In questo codice:

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

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

... la selfvariabile rappresenta l'istanza dell'oggetto stesso. La maggior parte dei linguaggi orientati agli oggetti passa questo come parametro nascosto ai metodi definiti su un oggetto; Python no. Devi dichiararlo esplicitamente. Quando crei un'istanza della Aclasse e chiami i suoi metodi, verrà passata automaticamente, come in ...

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

Il __init__metodo è approssimativamente ciò che rappresenta un costruttore in Python. Quando chiami A()Python crea un oggetto per te e lo passa come primo parametro al __init__metodo. Eventuali parametri aggiuntivi (ad es. A(24, 'Hello')) Verranno inoltre passati come argomenti, in questo caso causando la generazione di un'eccezione, poiché il costruttore non li prevede.


8
cosa succede se si mette x = 'Hello'al di fuori di init ma all'interno della classe? è come Java dove è uguale o diventa una variabile statica che viene inizializzata una sola volta?
Jayen,

15
È come una variabile statica. Viene inizializzato solo una volta ed è disponibile tramite A.xo a.x. Nota che sovrascriverlo su una classe specifica non influirà sulla base, quindi A.x = 'foo'; a.x = 'bar'; print a.x; print A.xstamperà barquindifoo
Chris B.

156
Vale la pena sottolineare che il primo argomento non deve necessariamente essere chiamato self, è solo per convenzione.
Henry Gomersall,

13
Qual è il punto objectnella dichiarazione di classe? Ho notato che alcune lezioni hanno questo e altri no
Chris,

9
@Chris È per la compatibilità con Python 2. In Python 3 non è necessario ereditare esplicitamente objectperché accade per impostazione predefinita.
Gabriel,

241

Sì, hai ragione, questi sono costrutti oop.

__init__è il costruttore di una classe. Il selfparametro si riferisce all'istanza dell'oggetto (come thisin C ++).

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

Il __init__metodo viene chiamato quando viene allocata la memoria per l'oggetto:

x = Point(1,2)

È importante utilizzare il selfparametro all'interno del metodo di un oggetto se si desidera mantenere il valore con l'oggetto. Se, ad esempio, si implementa il __init__metodo in questo modo:

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

Le vostre xe yparametri saranno memorizzati in variabili nello stack e sarebbero scartati quando il metodo init esce dallo scope. Impostando tali variabili come self._xe self._yimpostando tali variabili come membri Pointdell'oggetto (accessibile per la durata dell'oggetto).


1
Quindi c'è qualche motivo per cui non vorresti selfessere nel costruttore? Perché devi anche specificarlo, non sarebbe meglio se fosse implicito?
Aaron Franke,

Per quanto ne so, __ init __ non è un costruttore, è il primo metodo che verrà eseguito quando viene creato un oggetto, __ init __ viene utilizzato per impostare l'oggetto. __ nuovo __ è il costruttore in Python.
Deepanshu,

207

Un breve esempio illustrativo

Nella speranza che possa aiutare un po ', ecco un semplice esempio che ho usato per capire la differenza tra una variabile dichiarata all'interno di una classe e una variabile dichiarata all'interno di una __init__funzione:

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

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

Produzione:

345
123

7
Osservazione interessante ma penso che tu sia sulla strada sbagliata. Con print MyClass.i sembra più che tu stia chiamando una variabile 'statica' i. Laddove, come ai, stai chiamando una variabile membro, i. Mi sembra che init sia solo un costruttore che viene eseguito per la prima volta quando si crea un oggetto della classe.
captainspi,

34
Questo è quello che stavo cercando di "spiegare a me stesso" con questo esempio: che la variabile impostata da __init__è ciò che viene passato alle istanze della classe, non la variabile "statica" della classe stessa che ha lo stesso nome ...
Dave Everitt il

44

In breve:

  1. selfcome suggerisce, si riferisce a se stesso - l'oggetto che ha chiamato il metodo. Cioè, se hai N oggetti che chiamano il metodo, allora self.afaranno riferimento a un'istanza separata della variabile per ciascuno degli N oggetti. Immagina N copie della variabile aper ogni oggetto
  2. __init__è ciò che viene chiamato come costruttore in altri linguaggi OOP come C ++ / Java. L'idea di base è che si tratta di un metodo speciale che viene chiamato automaticamente quando viene creato un oggetto di quella Classe

29

__init__si comporta come un costruttore. Dovrai passare "self" a qualsiasi funzione di classe come primo argomento se vuoi che si comportino come metodi non statici. "self" sono variabili di istanza per la tua classe.


1
'self' definisce se un metodo è statico o no! Wow, questo è un colpo d'occhio per questo ragazzo di Java.
liwevire il

25

Prova questo codice. Spero che aiuti molti programmatori C come me ad imparare Py.

#! /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__

Produzione:

Jay

Sum = 5

Doc - Inside Class

Doc - __init__ Constructor

Doc - Inside Show

Destructor Deleting object - Jay


Non so se sono solo io, ma leggere questo codice è stato un po 'confuso. Forse è perché sono ancora un programmatore principiante di Python, idk.
Linny,

Non sono chiaro sull'aspetto del documento ... estrae la documentazione? e se lo faccio: '' 'test - my doc' '', posso usare: print.p .__ test__? o doc è una parola chiave specifica?
Thomas,

@Thomas doc è la parola chiave per i dettagli documentati. Le virgolette triple sono usate per scrivere documenti e il documento è un'entità opzionale.
Jayzcode,

25

Gli oggetti di classe supportano due tipi di operazioni: riferimenti di attributo e istanza

I riferimenti agli attributi utilizzano la sintassi standard utilizzata per tutti i riferimenti agli attributi in Python: nome_oggetto. I nomi di attributo validi sono tutti i nomi presenti nello spazio dei nomi della classe al momento della creazione dell'oggetto di classe. Quindi, se la definizione della classe sembrava così:

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

    def f(self):
        return 'hello world'

quindi MyClass.ie MyClass.fsono riferimenti di attributi validi, che restituiscono rispettivamente un numero intero e un oggetto funzione. È inoltre possibile assegnare attributi di classe, quindi è possibile modificare il valore di MyClass.iper assegnazione. __doc__è anche un attributo valido, che restituisce il docstring appartenente alla classe: "Una semplice classe di esempio".

L'istanza di classe utilizza la notazione di funzione. Fai solo finta che l'oggetto class sia una funzione senza parametri che restituisce una nuova istanza della classe. Per esempio:

x = MyClass()

L' operazione di istanza ("chiamata" di un oggetto di classe) crea un oggetto vuoto. Molte classi amano creare oggetti con istanze personalizzate per uno stato iniziale specifico. Pertanto una classe può definire un metodo speciale chiamato __init__(), in questo modo:

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

Quando una classe definisce un __init__()metodo, l'istanza di classe richiama automaticamente l'istanza di classe __init__()appena creata. Quindi, in questo esempio, è possibile ottenere una nuova istanza inizializzata da:

x = MyClass()

Naturalmente, il __init__()metodo può avere argomenti per una maggiore flessibilità. In tal caso, gli argomenti forniti all'operatore di istanza di classe vengono passati a __init__(). Per esempio,

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

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

Tratto dalla documentazione ufficiale che mi ha aiutato di più alla fine.


Ecco il mio esempio

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 :)")

Quando si crea un'istanza della classe Bill:

purchase = Bill(5,6,7)

Ottieni:

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

22

Ho avuto difficoltà a capirlo da solo. Anche dopo aver letto le risposte qui.

Per comprendere correttamente il __init__metodo è necessario capire se stessi.

L'auto-parametro

Gli argomenti accettati dal __init__metodo sono:

def __init__(self, arg1, arg2):

Ma in realtà passiamo solo due argomenti:

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

Da dove viene l'argomento extra?

Quando accediamo agli attributi di un oggetto lo facciamo per nome (o per riferimento). Qui l'istanza è un riferimento al nostro nuovo oggetto. Accediamo al metodo printargs dell'oggetto di istanza usando instance.printargs.

Per accedere agli attributi degli oggetti all'interno del __init__metodo è necessario un riferimento all'oggetto.

Ogni volta che viene chiamato un metodo, un riferimento all'oggetto principale viene passato come primo argomento. Per convenzione chiami sempre questo primo argomento sul tuo metodo.

Ciò significa che nel __init__metodo possiamo fare:

self.arg1 = arg1
self.arg2 = arg2

Qui stiamo impostando gli attributi sull'oggetto. Puoi verificarlo procedendo come segue:

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

valori come questo sono noti come attributi di oggetto. Qui il __init__metodo imposta gli attributi arg1 e arg2 dell'istanza.

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


17

nota che selfpotrebbe effettivamente essere qualsiasi identificatore python valido. Ad esempio, potremmo altrettanto facilmente scrivere, dall'esempio di Chris B.

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

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

e funzionerebbe esattamente allo stesso modo. Si consiglia comunque di usare sé perché altri pitoni lo riconosceranno più facilmente.


Sono d'accordo che il sé sarebbe raccomandato al posto di foo, aiuta altri programmatori a guardare il codice
Linny,

15

Fondamentalmente, è necessario utilizzare la parola chiave 'self' quando si utilizza una variabile in più funzioni all'interno della stessa classe. Per quanto riguarda init , viene utilizzato per impostare i valori predefiniti in caso non vengano chiamate altre funzioni all'interno di quella classe.


6
Non esiste una parola chiave "self" in Python. Chiamare il primo parametro 'self' è semplicemente una convenzione.
David Anderson,

il sé viene utilizzato come segnaposto in pratica. Non è necessario che usi self, puoi usare "eeee" o "foo" o qualcos'altro, è consigliato solo ad altri programmatori durante la lettura del tuo codice
Linny,

15
  1. __init__è fondamentalmente una funzione che "inizializza" / "attiva" le proprietà della classe per un oggetto specifico, una volta creata e abbinata alla classe corrispondente.
  2. self rappresenta quell'oggetto che erediterà quelle proprietà.

1
la parola chiave "self" non deve essere utilizzata, è solo un segnaposto. Puoi usare qualsiasi parola, ma è consigliabile usare self per aiutare la leggibilità del programma
Linny,

13

Il 'sé' è un riferimento all'istanza della classe

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

Ora possiamo creare un'istanza di foo e chiamare il metodo su di essa, il parametro self viene aggiunto da Python in questo caso:

f = foo()
f.bar()

Ma può essere passato anche se la chiamata al metodo non è nel contesto di un'istanza della classe, il codice seguente fa la stessa cosa

f = foo()
foo.bar(f)

È interessante notare che il nome della variabile 'sé' è solo una convenzione. La definizione che segue funzionerà esattamente allo stesso modo. Detto che è una convenzione molto forte che dovrebbe essere seguita sempre , ma dice qualcosa sulla natura flessibile della lingua

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

Perché questo dice qualcosa sulla natura flessibile della lingua? Dice solo che puoi dare alle variabili qualsiasi nome legale tu scelga. In che modo differisce da qualsiasi altro linguaggio di programmazione?
Daniel,

Come ho scritto nella mia risposta "barra" è solo una funzione in cui viene fornita un'istanza di classe come primo parametro. Quindi, mentre "bar" è definito come un metodo associato a "pippo", potrebbe anche essere chiamato con un'istanza di qualche altra classe. Questo non è il modo in cui i metodi e "questo" funzionano ad esempio in Java, anche se immagino che questi siano gli stessi concetti, le stesse funzioni e alcuni contesti di istanza (il contesto dell'istanza è il primo parametro in Python e "questo" in Java ") Forse ora puoi vedere la flessibilità della lingua a cui mi riferivo?
tarn,

Sì, questo dimostra la flessibilità della lingua. Nel modo in cui hai espresso la tua risposta, sembra che tu stia dicendo che il fatto di poter chiamare la variabile "sé" qualcos'altro (come s) stava mostrando la flessibilità di Python.
Daniel,

12

Solo una demo per la domanda.

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

11

In questo codice:

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

Qui __init__funge da costruttore per la classe e quando un oggetto viene istanziato, questa funzione viene chiamata. selfrappresenta l'oggetto istanziante.

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

Il risultato delle dichiarazioni precedenti sarà il seguente:

I am a cat and I am called Kitty

11

Cosa fa se stesso ? Cosa significa essere? È obbligatorio ?

Il primo argomento di ogni metodo di classe, incluso init, è sempre un riferimento all'istanza corrente della classe . Per convenzione, questo argomento è sempre chiamato self. Nel metodo init,self riferisce all'oggetto appena creato; in altri metodi di classe, si riferisce all'istanza il cui metodo è stato chiamato.

Python non ti costringe a usare " self ". Puoi dargli il nome che vuoi. Ma ricorda che il primo argomento nella definizione di un metodo è un riferimento all'oggetto . Python aggiunge l' selfargomento all'elenco per te; non è necessario includerlo quando si chiamano i metodi. se non hai fornito il metodo self in init, otterrai un errore

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

Cosa fa il metodo init ? Perché è necessario (eccetera.)

initè l'abbreviazione di inizializzazione. È un costruttore che viene chiamato quando si crea un'istanza della classe e non è necessario . Ma di solito è nostra prassi scrivere il metodo init per impostare lo stato predefinito dell'oggetto. Se inizialmente non si desidera impostare alcuno stato dell'oggetto, non è necessario scrivere questo metodo.


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()

5

Python __init__e selfcosa fanno?

Cosa fa self ? Cosa significa essere? È obbligatorio?

Cosa fa il __init__metodo? Perché è necessario (eccetera.)

L'esempio fornito non è corretto, quindi lasciami creare un esempio corretto basato su di esso:

class SomeObject(object):

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

    def method(self):
        return self.blah 

Quando creiamo un'istanza dell'oggetto, __init__viene chiamato per personalizzare l'oggetto dopo che è stato creato. Cioè, quando chiamiamo SomeObjectcon 'blah'seguito (che potrebbe essere qualsiasi cosa), che viene passato alla __init__funzione di come argomento, blah:

an_object = SomeObject('blah')

L' selfargomento è l'istanza SomeObjectche verrà assegnata aan_object .

In seguito, potremmo voler chiamare un metodo su questo oggetto:

an_object.method()

Facendo la ricerca punteggiata, cioè an_object.method , associa l'istanza a un'istanza della funzione e il metodo (come chiamato sopra) ora è un metodo "associato", il che significa che non è necessario passare esplicitamente l'istanza alla chiamata del metodo .

La chiamata del metodo ottiene l'istanza perché era associata alla ricerca punteggiata e, quando chiamata, esegue quindi qualsiasi codice programmato per l'esecuzione.

L' selfargomento implicitamente passato è chiamato selfper convenzione. Potremmo usare qualsiasi altro nome Python legale, ma probabilmente verrai tarato e sfumato da altri programmatori Python se lo cambi in qualcos'altro.

__init__è un metodo speciale, documentato nella documentazione del modello di dati Python . Viene chiamato immediatamente dopo la creazione dell'istanza (in genere tramite __new__- sebbene __new__non sia necessario a meno che non si stia eseguendo la sottoclasse di un tipo di dati immutabile).


3

Qui, il ragazzo ha scritto abbastanza bene e semplice: https://www.jeffknupp.com/blog/2014/06/18/improve-your-python-python-classes-and-object-oriented-programming/

Leggi il link sopra come riferimento a questo:

self? Allora, che cosa è con quel parametro per tutti i metodi del cliente? Che cos'è? Perché, è l'istanza, ovviamente! Detto in altro modo, un metodo come Prelievo definisce le istruzioni per il prelievo di denaro dal conto di un cliente astratto. Chiamare jeff.withdraw (100.0) mette queste istruzioni da usare nell'istanza jeff.

Quindi, quando diciamo def ritirare (sé, importo):, stiamo dicendo, "ecco come si preleva denaro da un oggetto Cliente (che chiameremo sé) e una cifra in dollari (che chiameremo importo). è l'istanza del Cliente a cui viene richiesto il prelievo. Non sono io che faccio analogie. jeff.withdraw (100.0) è solo una scorciatoia per Customer.withdraw (jeff, 100.0), che è perfettamente valido (se non visto spesso) codice.

init self può avere senso per altri metodi, ma che dire di init ? Quando chiamiamo init , siamo in procinto di creare un oggetto, quindi come può esserci già un sé? Python ci consente di estendere il modello di sé anche quando vengono costruiti oggetti, anche se non si adatta esattamente. Immagina che jeff = Customer ('Jeff Knupp', 1000.0) sia lo stesso che chiamare jeff = Customer (jeff, 'Jeff Knupp', 1000.0); anche il jeff che è passato è il risultato.

Questo è il motivo per cui quando chiamiamo init , inizializziamo gli oggetti dicendo cose come self.name = name. Ricorda, poiché self è l'istanza, questo equivale a dire jeff.name = name, che è lo stesso di jeff.name = 'Jeff Knupp. Allo stesso modo, self.balance = balance è uguale a jeff.balance = 1000.0. Dopo queste due righe, consideriamo l'oggetto Cliente "inizializzato" e pronto per l'uso.

Stai attento a cosa tu __init__

Dopo che init ha terminato, il chiamante può giustamente supporre che l'oggetto sia pronto per l'uso. Cioè, dopo jeff = Customer ('Jeff Knupp', 1000.0), possiamo iniziare a effettuare depositi e ritirare chiamate su jeff; jeff è un oggetto completamente inizializzato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.