18 settembre, 2019

Copia di oggetti in Python


In qualche misura è la continuazione di questo post, anche se il titolo dev'essere completamente differente.

Esaurito il capitolo global ci sono ancora un paio di aspetti che a volte --se non faccio attenzione-- non vanno come --ingenuamente-- mi verrebbe da pensare; anche se... --OK, racconto.

Passando oggetti diversi da numeri a una funzione cosa succede? Devo elencarli nel return? o preoccuparmi del valore originale? Un esempio che chiarisce (dovrebbe, spero).

def func(i, f, ls, dic, st):
    i = i * 2
    f = f * 3
    ls[0] = 'cambio'
    ls[1] = 'qui'
    dic['due'] = 2
    st = st.upper() + ' modificata'
    return i, f, st

# main
i = 4
f = 1.2
ls = [1, 2, 3, 4]
dic = {'uno' : 1}
st = 'stringa'
ir, fr, stm = func(i, f, ls, dic, st)
print(i, f)
print(ir, fr)
print(ls)
print(dic)
print(st)
print(stm)


eseguo e ottengo:

$ py3 obj.py
4 1.2
8 3.5999999999999996
['cambio', 'qui', 3, 4]
{'uno': 1, 'due': 2}
stringa
STRINGA modificata
$


Uh! vediamo in dettaglio:
  • i valori originali delle variabili numeriche (i e f) non cambiano e i valori dell'elaborazione devo elencarli in return e tra quanto ritorna la funzione (ir e fr);
  • la lista (ls) passata alla funzione viene modificata, e ritornata modificata, l'originale è perso;
  • la stessa cosa capita per i dizionari (dic), le tuple, gli array, e altri oggetti (non presenti nell'esempio);
  • le stringhe (che in certi linguaggi sono array, p.es C) si comportano come i numeri.

C'è un altra cosa che a volte... copiare oggetti. Ecco un esempio con le liste:

a = [1, 2, 3]
print(a)
b = a
b[0] = 'X'
print(a)
print(b)


$ py3 cp1.py
[1, 2, 3]
['X', 2, 3]
['X', 2, 3]
$


OOPS! la modifica di b ha modificato a! non quello che mi aspettavo. C'è il modulo copy per questo con due funzioni per copiare. Uso liste per gli esempi, ovviamente vale non solo per loro.

la funzione copy.copy() funziona solo per le liste lineari (non so se il termine è corretto), cosi:

import copy

a = [1, 2, 3]
print(a)
b = copy.copy(a)
b[1] = 'X'
print(a)
print(b)


$ py3 cp2-0.py
[1, 2, 3]
[1, 2, 3]
[1, 'X', 3]
$


ma non per liste dentro la lista:

import copy

a = [1, [2, 'a', 'b'], 3]
print(a)
b = copy.copy(a)
b[1][1] = 'X'
print(a)
print(b)


$ py3 cp2-1.py
[1, [2, 'a', 'b'], 3]
[1, [2, 'X', 'b'], 3]
[1, [2, 'X', 'b'], 3]
$


in questo caso devo ricorrere a copy.deepcopy()

import copy

a = [1, [2, 'a', 'b'], 3]
print(a)
b = copy.deepcopy(a)
b[1][1] = 'X'
print(a)
print(b)


$ py3 cp3.py
[1, [2, 'a', 'b'], 3]
[1, [2, 'a', 'b'], 3]
[1, [2, 'X', 'b'], 3]
$

🔴

Nessun commento:

Posta un commento