Perché hai bisogno di "io". in Python per fare riferimento alle variabili di istanza?


13

Ho programmato in diversi linguaggi come Java, Ruby, Haskell e Python. Devo passare da una lingua all'altra a causa di diversi progetti su cui lavoro. Ora, il problema è che spesso dimentico di scrivere selfcome il primo parametro nelle definizioni delle funzioni in Python stesso è con i metodi di chiamata sullo stesso oggetto.

Detto questo, sono abbastanza sorpreso da questo approccio di Python. Fondamentalmente dobbiamo scrivere di più per fare le cose, in linguaggi come Java e Ruby le cose sono rese semplici facendo riferimento automaticamente alle variabili nell'oggetto corrente.

La mia domanda è: perché è selfnecessario? È semplicemente una scelta di stile o c'è un motivo per cui Python non può lasciarti omettere selfdal modo in cui Java e C ++ ti fanno omettere this?



1
@gnat ora solo professionisti, e seriamente è una buona domanda che mi infastidisce da pochi giorni, per favore non ucciderlo con il voto negativo.
vivek,

2
Questa domanda è stata più che approfondita da stackoverflow.com/questions/2709821/… .
David Arno,

La mia comprensione è che si basa sullo stile C di passare un puntatore a una struttura come primo argomento.
Dannnno,

Scrivere @staticmethodprima della dichiarazione del metodo, elimina l'errore (solo per informazioni e anche non consigliato)
Yash

Risposte:


23

1) Perché è selfrichiesto come parametro esplicito nelle firme del metodo?

Perché i metodi sono funzioni ed foo.bar(baz)è solo zucchero sintattico per bar(foo, baz). Le classi sono solo dizionari in cui alcuni dei valori sono funzioni. (I costruttori sono anche solo funzioni, motivo per cui Python non ha bisogno new) Puoi dire che Python rende esplicito che gli oggetti sono costruiti da componenti più semplici. Ciò è in accordo con la filosofia "esplicito è meglio che implicito".

Al contrario, in Java gli oggetti sono davvero magici e non possono essere ridotti a componenti più semplici nel linguaggio. In Java (almeno fino a Java 8) una funzione è sempre un metodo di proprietà di un oggetto e questa proprietà non può essere modificata a causa della natura statica della lingua. Pertanto non vi è alcuna ambiguità su ciò che si thisriferisce, quindi ha senso averlo implicitamente definito.

JavaScript è un esempio di un linguaggio che ha un implicito thiscome Java, ma in cui le funzioni possono esistere separatamente da oggetti come in Python. Questo porta a molta confusione su ciò che si thisriferisce a quando le funzioni vengono passate e chiamate in contesti diversi. Molti istintivamente pensano che thisdebba fare riferimento ad alcune proprietà intrinseche della funzione, mentre in realtà è puramente determinato dal modo in cui viene chiamata la funzione. Credo che avere thisun parametro esplicito come in Python renderebbe questo molto meno confuso.

Alcuni altri vantaggi del selfparametro esplicito :

  • I decoratori sono solo funzioni che avvolgono altre funzioni. Poiché i metodi sono solo funzioni, i decoratori funzionano altrettanto bene sui metodi. Se ci fosse una sorta di sé implicito, i decoratori non lavorerebbero in modo trasparente sui metodi.

  • Metodi di classe e metodi statici non accettano un parametro di istanza. I metodi di classe prendono una classe come primo argomento (in genere chiamato cls). L'esplicito selfo i clsparametri rendono molto più chiaro cosa sta succedendo e ciò a cui si ha accesso nel metodo.

2) Perché le variabili delle istanze devono sempre essere qualificate con " self.?

In Java, non è necessario aggiungere il prefisso alle variabili membro con " this.", ma in Python " self." è sempre richiesto. Il motivo è che Python non ha una sintassi esplicita per dichiarare le variabili, quindi non ci sarebbe modo di dire se x = 7si suppone che debba dichiarare una nuova variabile locale o assegnare a una variabile membro. Specificare self.risolve questa ambiguità.


Il riferimento alla variabile membro implicito (senza self., come Java) è fondamentalmente incompatibile con le regole di scoping e quando è necessario essere espliciti lì, essere impliciti sul parametro non ha più molto senso.
Jan Hudec,

@JanHudec: Bene, punto. L'ho aggiunto alla risposta.
Jacques B

6

C'è una ragione piuttosto semplice per cui AFAIK non è stato toccato nel duplicato cross-site, né qui: Python è iniziato come un linguaggio procedurale. Si basava su ABC, anche un linguaggio procedurale.

L'orientamento agli oggetti è stato aggiunto in seguito e, quando è stato aggiunto, Guido van Rossum ha voluto aggiungere la minima quantità possibile di funzionalità, al fine di mantenere semplice il design di Python. Python aveva già dicts e funzioni, quindi perché aggiungere qualcosa di completamente nuovo al linguaggio, quando un oggetto può essere semplicemente una dictdelle slot e una classe può semplicemente essere una dictdelle funzioni? Un metodo può essere interpretato come una funzione parzialmente applicata che si chiude su un singolo argomento distinto. Ed è proprio così che i metodi sono implementati in Python: non lo sono. Sono solo funzioni che ricevono un argomento distinto in più.


Credo che Python supportasse OO e avesse classi ed eredità dalla prima versione rilasciata. Almeno questo è ciò che mi dice Wikipedia. Ma il processo di Van Rossums nella progettazione iniziale del linguaggio potrebbe essere stato come lo descrivi.
Jacques B


Grazie per il link, questa lettura è davvero interessante.
Jacques B,

2

Ecco le mie conclusioni sulla base sopra le risposte e la lettura proprio del Guido vagante su questo argomento:

La grande idea

Le funzioni sono gli elementi costitutivi importanti in Python (o dovremmo dire l'unico), in effetti stiamo emulando OOP usando le funzioni.

Dato che una classe non è altro che un dizionario di funzioni quindi, possiamo associare qualsiasi funzione a qualsiasi classe in fase di esecuzione. Fondamentalmente è a causa di questa necessità di lanciare le funzioni in fase di esecuzione che possiamo fare cose come Monkey Patching . Qui il selfparametro che supporta il polimorfismo parametrico.


1
Le domande a risposta autonoma sono incoraggiate quando la risposta è di alta qualità. Quando confronterò la tua risposta qui con le altre risposte, mi chiederò perché hai sentito di dover aggiungere questa. Le altre risposte vanno più in profondità e aggiungono più dettagli di quello che fa la tua risposta.

1
@ GlenH7 la risposta è stata solo per mio riferimento perché ogni volta che non posso venire a leggere la risposta di tutti ancora e ancora. Per quanto riguarda la qualità, dimmi se qualche informazione è fuorviante. Ad ogni modo, in genere aspetto 2-3 giorni per accettare qualsiasi risposta.
vivek,

Il voto negativo sta diventando una valuta economica e tutti qui la stanno spendendo con entrambe le mani senza conoscerne il significato. Ti rendi conto che se qualcuno viene qui, vedi questa risposta votata per scontata, assumerebbe che sia sbagliata!
vivek,
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.