Ciclo for (per capire)

a = []
for i in range(3):
	print "ID", i
	b = []
	a.append(b)
	print a # print previsto ma con risultato errato
	for j in range(3):
		b.append(3*i+j)
	print a # print col risultato desiderato ma non previsto

Risultato Print:

>>> 
ID 0
[[]]
[[0, 1, 2]]
ID 1
[[0, 1, 2], []]
[[0, 1, 2], [3, 4, 5]]
ID 2
[[0, 1, 2], [3, 4, 5], []]
[[0, 1, 2], [3, 4, 5], [6, 7, 8]]
>>> 

ragazzi aiutatemi a capire sta cosa perché non mi torna proprio (i primi segni di vecchiaia anticipata)

ciò che volevo ottenere è il risultato del secondo print, ma osservando il codice, il secondo print non capisco perché è diverso dal primo. per quanto mi riguarda dovrebbero tornare entrambi lo stesso risultato?

è mai possibile che Python aggiorni il valore di a.append nella seconda parte del ciclo for?

Salvio, sei una manna per i pensionati che vogliono tenere allenato il cervello …
:wink: :smile:

Perche’ tra il primo e il secondo print hai messo un bel ciclo che appende 3 valori a b,
quindi b e’ cambiato, no ?

Il valore di a.append() non so cosa sia … :smile:
Il valore di a non cambia, nel senso che contiene sembre solo b, ma e’ b che cambia,
quindi a cambia di conseguenza.

Se tu hai il portafoglio in tasca con 10 euro
e poi aggiungi altri 20 euro nel portafoglio,
la tua tasca conterra’ sempre lo stesso portafoglio, quindi non cambia,
ma il portafoglio conterra’ 30 euro, quindi, se consideriamo la cifra totale, la tua tasca e’ cambiata.

Ovviamente la tasca e’ ‘a’ e il portafoglio e’ ‘b’. :grinning:

3 Mi Piace

e io dopo tutto questo tempo credevo che a incorporasse “il valore di b” (una copia per intenderci)
invece incorpora direttamente la variabile. quindi append funziona come quando si scrive a=b :+1:

ps si nota che è un pò di tempo che non uso python :smiling_face: :smiling_face:

edit: per lo meno il codice è scritto bene quindi . . . .

Non proprio.
Python e’ complicatuccio in queste cose secondo me … :confused:

Le variabili di solito non sono nemmeno chiamate variabili ma nomi, in Python.
Questo appunto perche’ di solito una variabile contiene qualcosa, mentre i nomi di Python non contengono niente, ma sono solo legati (bound) a dei valori, i quali valori hanno vita propria, per cosi’ dire, esistono indipendentemente dal fatto che siano legati a uno o piu’ nomi.

Quando assegni un valore ad un nome si crea un legame (binding).
E se il valore in questione e’ dato da un’altra variabile, ad esempio

a = b

Quello che succede e’ che si crea un nuovo legame tra il valore di a e il nome b.
Per cui entrambi i nomi sono legati allo stesso valore.

Tutto cio’ non da’ problemi per valori immutable, perche’ che tu copi il valore o meno il risultato non cambia, tanto quel valore non puo’ piu’ mutare.

Con i valori mutable, come le liste, la cosa diventa molto piu’ divertente … :wink:
Perche’ se tu assegni un valore a una variabile e poi lo modifichi, anche la variabile, chiamiamola cosi’, vedra’ il valore modificato.

Occhio pero’ che il legame e’ con il valore dell’altra variabile, non con il suo nome.
Per cui se tu scrivi cosi’

a = 8
b = a
a = 4

b vale sempre 8, non diventa 4.

Eeeeeh … in effetti … :wink: :smile: :smile: :smile:

1 Mi Piace

alla fine però non ero fuori strada quindi, perché in questo caso per riaggiornare b bisogna ripetere b=a

eeee non dirmelo a me, non so se vba funziona diversamente ma non mi era mai capitato una cosa simile
ovviamente poi io ci metto il mio, (essendo che anche se fosse) io tendo a pensare che il funzionamento sia simile e casco sempre nel tranello di dare per scontato delle circostanze che possono sembrare banali essendo simili ma che alla fine non’é è detto che il for di vba/vbs funzioni come il for di python ecc

però poi quando si pensa di aver capito un qualcosa in più, Emilio tira fuori una frase come questa
e li alla fine, invece di fare un passo in avanti ne faccio dieci in dietro ahahahah :sweat_smile: :sweat: :tired_face:

sperando di aver afferrato la situazione e ricapitolando il tutto:

a=8
b=a
a=4

a diventa 4 mentre b rimane 8 (e questo è sempre stata la mia pietra miliare) mentre:

a=[]
b=[]

a.append(b)
a e b sono entrambi liste vuote ma se
b.append(“Emilio”)
in questo caso abbiamo 1 Emilio nella lista b ed un “richiamo” sempre a Emilio di b nella lista a

nel primo caso la b incorpora il valore di a “solo” quando richiamato dall’istruzione
mentre nel secondo caso invece abbiamo la lista di b all’interno della lista di a
quindi quando si aggiorna b si aggiorna automaticamente anche all’interno di a

spero che il riassunto sia corretto :rofl: :rofl:

ps in pratica tutto questo è collegato al prossimo post . . . .

edit:

mi sa che quest’anno verrò rimandato :rofl: :sweat_smile:

a e’ vuota prima di:

a.append(b)

dopo diventa:

[[]]

Parli di questa istruzione ?

b=a

Cosa intendi con “solo” ?
Ovviamente prima di quella istruzione b non esiste nemmeno
e dopo e’ legata ad un valore che ha ricavato da a, almeno finche’ non assegni a b un altro valore.

Non capisco il “solo” … :confused:

Quale prossimo post ???
Cosa ti stai inventando ? :smile:

EDIT

OK, ho visto.
Si tratta di tipi di dati particolari di GH.
Ci vogliono gli esperti di GH. :slight_smile:

hai ragione, intendevo dire che a differenza del secondo esempio delle liste: a.append(b) se la lista b cambia cambia anche a. mentre nel primo caso: b=a ma se a cambia per cambiare b bisogna ripetere b=a
“quindi era per dire che non cambia in automatico ma cambia “solo” richiamare l’istruzione b=a”
(ovviamente prendendo in considerazione gli esempi fatti)

OK, chiaro.

In realta’ il meccanismo e’ sempre lo stesso nei due casi.
Scrivere:

a = 8
b = a
a = 4

E’ come scrivere:

a = [ 1, 2 ]
b = a
a = [ 3, 4 ]

In entrambi i casi se assegni un nuovo valore ad ‘a’, il valore di ‘b’ non cambia.
‘b’ rimane legata al ‘vecchio’ valore di ‘a’.

Diverso e’ il caso:

a = [ 1, 2 ]
b = a
a.append( 3 )

Qui non assegni un nuovo valore, ma modifichi il valore di ‘a’ senza sostituirlo,
quindi anche ‘b’, che e’ legata al ‘vecchio’ valore di ‘a’ cambia.
proprio perche’ il vecchio valore non e’ stato sostituito, ma solo modificato,
in realta’ quel valore non e’ per niente ‘vecchio’ … e’ sempre lo stesso,
solo che, esendo un valore mutable, possiamo modificarlo quando vogliamo. :grinning:

2 Mi Piace

Emilio, mi hai anticipato :slight_smile: era proprio quello che volevo provare essendo che di for ne ho fatti tanti in vba mentre in python quei “non molti” fatti, in genere non andavo ad usare le liste ne tantomeno append
quindi non per spezzare una lancia in mio favore, ma mi sono ritrovato in una situazione nuova

concludendo il cambio automatico di b=a è una conseguenza non tanto della lista ma nell’uso di append

:+1:

edit: certo che però pensandoci, o è una regola che si conosce oppure non’é facile intuire che succeda,
in questo caso: a=[1,2] b=a poi a=[3,4] b non cambia mentre usando a.append(3) b cambia come a [1,2,3]

2 Mi Piace
>>> a=["",(),[]]
>>> b=a
>>> a[0]="wewe"
>>> print a,b
['wewe', (), []] ['wewe', (), []]
>>> a=[1234]
>>> print a,b
[1234] ['wewe', (), []]
>>> a=[]
>>> b=a
>>> a=["wewe"]
>>> a,b
(['wewe'], [])

Emilio andando a fare altre prove venute in mente, bisogna stare ancora più attenti
credevo che andando a cambiare solo gli indici venissero separate le associazioni
invece rimangono associate fino a che non viene re-inizializzata la variabile madre

Questo di solito si chiama “assegnare un valore a un elemento della lista” … o qualcosa di simile. :smile:

E questo di solito si chiama “assegnare un valore alla variabile” … ( come sopra ).

Cioe’ credevi che assegnano un valore a un elemento della lista legata sia al nome ‘a’ che al nome ‘b’, ‘b’ assumesse un nuovo valore, cioe’ il valore di ‘b’ diventasse diverso da quello di ‘a’. :slight_smile:

Temo che questo voglia dire che il mio tentativo di spiegazione precedente non e’ andato a buon fine … :confused:
Cioe’ non sono stato chiaro … :blush:

Forse questa faccenda di ‘nomi’ e ‘legami’ confonde.

Potremmo provare a considerare la cosa in modo diverso.
Diciamo che le variabili di Python sono ‘indirette’ … cioe’ non contengono direttamente i valori che utilizziamo nel nostro script, ma contengono dei puntatori (o riferimenti) ai valori.
I quali valori … risiedono (per cosi’ dire) da un’altra parte, in un quartiere diverso da quello delle variabili.
E nella variabile c’e’ l’indirizzo del valore. :wink:

Altra cosa fondamentale e’ la differenza tra valori ‘mutable’ e valori ‘immutable’.
I valori mutable possono essere modificati (esempio: liste)
I valori immutable non possono essere modificati (esempi: numeri, stringhe, tuple)

Ovviamente i valori immutable non danno problemi:
non esistono istruzioni per modificarli, possiamo solo assegnare alle variabili ogni volta un nuovo valore immutable.

a = 8
b = a
a -= 4

Qui ‘a’ vale 4 e ‘b’ vale 8.

Parlando di puntatori:

  1. a contiene un puntatore al valore 8
  2. b copia il valore di a, quindi anche lui contiene lo stesso puntatore allo stesso valore 8
  3. a ora contiene un nuovo puntatore, che punta ad un valore 4,
    ma b ovviamente non e’ cambiato, punta sempre ad 8

Con dati mutable le cose funzionano diversamente, pur con lo stesso meccanismo:

a = [ 1, 2 ]
b = a
a[ 0 ] = 11

Qui sia ‘a’ che ‘b’ valgono [ 11, 2 ], appunto perche’ , essendo la lista un valore mutable, e’ stato possibile modificarla, l’oggetto lista e’ rimasto lo stesso…

Coi puntatori:

  1. a contiene un puntatore ad una lista
  2. b copia il valore di a, quindi anche lui contiene un puntatore alla stessa lista
  3. un elemento di a riceve un nuovo valore, quindi la lista si modifica (si puo’ fare perche’ e’ mutable)
    b ovviamente punta sempre alla stessa unica lista, che pero’ e’ stata modificata.

Vedi che l’unica differenza dipende dal fatto che ‘a’ punti allo stesso valore oppure ad un nuovo valore.

A questo proposito, ho scoperto una cosa che non mi aspettavo … :confused:

>>> a = [ 1, 2 ]
>>> aa = [ 1, 2 ]
>>> aaa = [ 1, 2 ]
>>> b = a
>>> bb = aa
>>> bbb = aaa
>>> a.append( 3 )
>>> aa += [ 3 ]
>>> aaa = aaa + [ 3 ]
>>> b
[1, 2, 3]
>>> bb
[1, 2, 3]
>>> bbb
[1, 2]
>>>

… cioe’ con le liste += si comporta come append() e non come una normale assegnazione …
Strano.
Certo, se non fosse per i tuoi script io non avrei mai provato ad usare += con le liste … :smile:

1 Mi Piace

Emilio me ne ero accorto anch’io di questa cosa, infatti in una delle mie risposte iniziali credevo di averlo sottolineato ma mi sembra di non averlo citato, si vede che tra le tante domande fatte questa si era persa :blush:

al tuo esempio aggiungo anche il cambio dell’indice: aaaa

>>> a = [1, 2]
>>> aa = [1, 2]
>>> aaa = [1, 2]
>>> aaaa = [1, 2]
>>> b = a
>>> bb = aa
>>> bbb = aaa
>>> bbbb = aaa
>>> a.append(3)
>>> aa += [3]
>>> aaa = aaa + [3]
>>> aaaa[1] = 3
>>> a
[1, 2, 3]
>>> aa
[1, 2, 3]
>>> aaa
[1, 2, 3]
>>> aaaa
[1, 3]
>>> b
[1, 2, 3]
>>> bb
[1, 2, 3]
>>> bbb
[1, 2]
>>> bbbb
[1, 2]

ci sono due coppie (append) e (+=) poi (a = a + Valore) e (a[ID] = Valore) si comportano similmente

ps chissà se è voluta sta cosa, oppure chi ha scritto il codice del metodo contratto ( += ) non
sapendo che ( a = a + Valore ) da un risultato diverso da append al quale “credo” si sia ispirato

1 Mi Piace