Difference between revisions of "Parametro self in python"

From PNLUG
Jump to: navigation, search
(Created page with "Category:Guide = Il parametro self nei metodi Python = Molti si chiedono perché nei metodi delle classi python il primo parametro è sempre '''self''' e perché quando...")
(No difference)

Revision as of 08:29, 22 August 2018


Il parametro self nei metodi Python

Molti si chiedono perché nei metodi delle classi python il primo parametro è sempre self e perché quando si chiamo il metodo si passano i parametri dal secondo in poi. A prima vista sembra un comportamento incoerente, ma in realtà è vero proprio il contrario.

Il parametro self è una variabile che indica l’istanza corrente della classe, ed è presente i tutti i linguaggi orientati agli oggetti e serve a raggiungere i componenti dell’oggetto. In alcuni linguaggi si chiama this come ad esempio in java o in PHP, ed in alcuni casi può essere implicito, ad esempio in Delphi, e deve essere indicata solo se serve per distinguerla da variabili esterni o parametri, ad esempio in Delphi si può scrivere: this.abc := abc; in cui il primo abcè la variabile istanza, ed il secono è un parametro della funzione.

Facciamo un esempio

Scriviamo una piccola classe python:

$ python3
Python 3.5.2 (default, Nov 23 2017, 16:37:01) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> class Add():
...     def __init__(self):
...             self.value = 0
...     def add(self, num):
...             self.value += num
...             print(self.value)
... 
>>> a = Add()
>>> a.add(2)
2
>>> a.add(3)
5
>>> a.add(1,2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: add() takes 2 positional arguments but 3 were given
>>> 

Questo è il modo normale di scrivere le classi in python, vediamo che nella dichiarazione del metodo add abbiamo inseriro il parametro self seguito da un secondo parametro, ma poi nelle chiamate usiamo solo il secondo parametro, addirittura se faccio una chiamata con due parametri l’interprete mi da errore e dice che ho dato 3 parametri mentre ne erano richiesti solo due.

Python dinamico ed interattivo

Una cosa simile all’esempio precedente la possiamo fare a runtime.

Lo stile di programmazione che utilizziamo in genere dovrebbe essere evitato perché nelle applicazioni reali è difficile da leggere e manutenere, quando si scrivono programmi veri è sicuramete da scegliere la sintassi dell’esempio precedente. Ma in questo modo possiamo esporre alcune delle caratteristiche peculiari di Python che in alcuni casi lo rendono potente ed espressivo.

>>> class C1():
...     pass
... 
>>> c = C1()
>>> c.value = 0
>>> print(c.value)
0

ora definiamo una funzione:

>>> def add(self,num):
...     self.value += num
...     print(self.value)
... 
>>> add(c,2)
2
>>> add(c,3)
5

Come si vede, alla funzione viene passato come primo parametro l’oggetto istanziato in precedenza e correttamente interagisce con la variabile di istanza value

metodi e funzioni

Ora scriviamo:

>>> print(add)
<function add at 0x7faffdd9cd90>
>>> C1.add = add
>>> print(C1.add)
<function add at 0x7faffdd9cd90>

In questo modo ho aggiunto alla classe C1 la funzione add, fisicamente è lo stesso oggetto ed infatti punta alla stessa zona di memoria, ma è anche diventata un metodo della classe C2, infatti:

>>> c.add(3)
8

ma funziona ancora

>>> add(c,3)
11

Quindi, nella sintassi degli oggetti il parametro self è l’istanza di oggetto che chiama il metodo, nel nostro caso c.add(3) il parametro self è c.

Il motivo per cui è necessario dichiarare self nelle definizioni di metodi perciò è chiaro, è un parametro che viene comunque passato.

In questo senso Python è coerente ed esplicito, è l’unico linguaggio in cui il parametro self viene dichiarato tra i parametri dei metodi, ma per un buon motivo.

perchè si chiama self

In realtà si potrebbe chiamare in qualsiasi modo, infatti:

>>> def add(pippo,num):
...     pippo.value += num
...     print(pippo.value)
... 
>>> print(add)
<function add at 0x7faffdd9ce18>
>>> C1.add = add
>>> c.add(5)
16
>>> 

abbiamo ridefinito la funzione add, e siccome ora è un oggetto diverso l’abbiamo collegata nuovamente alla classe C1 e come si vede funziona anche se il parametro di istanza non si chiamo più self ma pippo.

Quindi se volete nei vosti script potete usare un nome diverso da self… purché non lo facciate vedere a nessuno :)

Tutti i programmatori python si aspettano che quel parametro si chiami self, è una convenzione, e non c’è nessun motivo valido per non rispettarla, e vi fareste del male da soli, perché in tutti i sorgenti python che vi capiterà di leggere troverete scritto self e quindi se lo usate anche voi nei vostri script, vi sarà più facile leggerli.