Supponiamo di voler scrivere una funzione che modifica un singolo attributo di un oggetto. In C possiamo implementare tale funzione essenzialmente in due modi:
- Codice:
Oggetto modifica_attributo(Oggetto o, Value v) {
Oggetto oc = o;
oc.attributo = v;
return oc;
}
void modifica_attributo(Oggetto *o, Value v) {
o->attributo = v;
}
In linea di massima la seconda implementazione sarà più efficiente perché non deve copiare tutto l'oggetto se questo fosse grande (nota tuttavia che la scelta di usare il passaggio per copia delle variabili non preclude la possibilità che il compilatore rimuova tale copia se la ritiene non necessaria). Ci sono però certamente delle situazioni in cui si desidera effettivamente una copia e quindi si deve seguire il primo approccio.
L'autore di Python ha probabilmente deciso che il secondo caso è il più comune e l'ha reso il comportamento di default. È tuttavia sempre possibile implementare entrambi i comportamenti anche in Python (anche se è più complicato):
- Codice:
import copy
def modifica_attributo(o, v):
oc = copy.copy(o)
oc.attributo = v
return oc
def modifica_attributo(o, v):
o.attributo = v
Nota che nel caso si scelga di passare i valori per copia come in C, per implementare il passaggio per riferimento esistono sostanzialmente due vie: definire un tipo puntatore/riferimento oppure usare una sintassi particolare come la seguente (in un finto linguaggio):
- Codice:
func modifica_attributo(ref o, v) do
o.attributo = v
end
Questa scelta permette di avere funzioni come questa oppure come swap, senza tuttavia avere un tipo puntatore con tutte le sue problematiche.
Vorrei infine osservare che queste NON sono le uniche scelte possibili, anche se per distinguere alcune delle scelte più complicate potrebbe essere necessario usare esempi più complicati.