Forum >> Principianti >> incremento variabile

Pagina: 1 2 3 Avanti

un saluto a tutti,
# x = 0
# y = 0
for z in range(9):
	if z % 2 == 0 : x += 1
	if z % 2 == 1 : y += 1
è da un bel pò di tempo che sto cercando un modo (se esiste) di incrementare una variabile "senza" dichiararle prima

ovviamente dichiarare le variabile serve ad assegnarle un banco di memoria, detto ciò sarebbe lo stesso possibile?

ps in python esiste una funzione a tale scopo o dispone di strumenti che combinati tra loro possono fare ciò?


--- Ultima modifica di pypy in data 2018-11-03 12:48:03 ---
Se proprio devi,

>>> for z in range(9):
...     if z % 2 == 0 : vars()["x"] = vars().get("x", 0) + 1
...     if z % 2 == 1 : vars()["y"] = vars().get("y", 0) + 1
... 
>>> x
5
>>> y
4


ma ricorda che Guido uccide un gattino ogni volta che usi questo codice.



THE 🍺-WARE LICENSE (Revision ㊷):
<㎝🐌🐍.🇮🇹> wrote this post. As long as you retain this notice you
can do whatever you want with this stuff. If we meet some day, and you
think this stuff is worth it, you can buy me a 🍺 in return. -- ㎝
>>> for z in range(9):
...     if z % 2 == 0 : vars()["x"] = vars().get("x", 0) + 1
...     if z % 2 == 1 : vars()["y"] = vars().get("y", 0) + 1
... 
>>> x
5
>>> y
4

Mamma mia, mi vengono i conati di vomito a vedere una cosa del genere. Anzi, ricordo una risposta di Guido proprio su una cosa del genere ed era profondamente turbato da tanta bruttezza.

Ma aggiungere al codice:
x = y = 0
...è così disturbante?

Pensaci bene pypy, non farlo, lascia che vivano quei poveri gattini. ;)
grazie cm per la soluzione, era da quando postai la domanda sulla funzione "enumerate" che mi era venuto questo grillo per la testa, credevo che combinandola con "lambda" riuscivo ad avere il risultato sperato ma come vedo ero proprio fuori strada, a questa soluzione non ci sarei mai arrivato "vars().get" non fa parte dei miei usi. ultimamente ho provato anche con una lista o "list comprehension" ma alla fine avevo capito che non ne sarei venuto a capo.

grazie anche a Daniele del consiglio. 1) beh che si potesse fare ne ero convinto. 2) che poteva essere contorta la cosa, ne avevo il presentimento. 3) ma che si facesse una strage di gattini ne ero completamente ingnaro di questo ahahahah

ps beh come sintassi infatti è un pochino bruttina da leggere, spero che la titubanza nel voler usare un codice come questo non sia anche dovuto a qualche imprevisto che potrebbe succedere in codici complessi, ma è solo un fatto di lettura?


ringrazio come sempre per ogni risposta che date a tutti gli iscritti per aiutarci nei nostri piccoli script :) volevo fare una ulteriore domanda riguardo tale argomento, anche se dico un mucchio di castronate sono in buona fede :embarrassed:

si potrebbe creare una funzione di default come ho citato "enumerate e lambda" che inserita in un ciclo "for o while" ogni volta che viene richiamata incrementa il valore della variabile inserita? mi spiego meglio facendo un esempio :

for n in range(10):
	funzione(x)
print(x) #output=10

oppure:

funzione(y)
funzione(y)
funzione(y)
print(y) #output=3
forse la cosa vi ha fatto ridere, ma in teoria dovrebbe essere fattibile creare una funzione o una classe che ogni volta che si inserisce una viriabile nuova la inizializza ed ogni volta che viene richiamata quella variabile incrementi il suo valore?


scusate le probabili bagianate ;)

Guarda, l'importante è che tu capisca:

a) che per lavorare su un oggetto (incrementarlo, o qualunque altra cosa) questo oggetto deve prima essere creato e deve essere in vita nel momento in cui ci vuoi lavorarci. Non è possibile lavorare su un oggetto che non è stato creato

b) che un oggetto resta in vita finché almeno una variabile si riferisce ad esso.

Dopo di che, scrivere banalmente "foo = 10" oppure in modo più esotico "vars()['foo'] = 10" è esattamente la stessa cosa. Non è certo per questo che può servirti una cosa come "vars()". E tutto il resto sono tecnicismi, che puoi imparare man mano, se vuoi. E se non vuoi, nessuno te ne farà una colpa...

> ultimamente ho provato anche con una lista o "list comprehension"
Ma certamente, puoi farlo con una list comprehension o in altri mille modi "cool":

>>> x = sum([1 for i in range(9) if i % 2 == 0])
>>> x
5
Ma non è che ti danno una medaglia per essere "cool".


> si potrebbe creare una funzione
> che ogni volta che viene
richiamata incrementa il valore della variabile inserita?
Si potrebbe e si dovrebbe, e si chiama "generatore" e questo invece prima o poi ti capiterà di studiarlo:

>>> def counter():
...     x = 0
...     while True:
...         yield x
...         x += 1
...
>>> c = counter()
>>> next(c)
0
>>> next(c)
1
>>> next(c)
2
>>> next(c)
3
>>> # eccetera...


ciao Ric e grazie dei tuoi esempi che hai postato

il fatto che un oggetto per essere incrementato deve essere prima creato sono daccordo, e non è per fare i fichi te lo assicuro anzi a volte perdo la testo per piccole porzioni di codici per cercare di semplificarli troppo. come si vede dall'esempio che ho fatto "funzione(x)" essendo che Python ha tante funzioni metodi potentissimi che fanno cose incredibili ritengo che non sarebbe ne complicato e non dovrebbe dare alcun effetto collaterale realizzare una funzione di "default" per incrementare una variabile senza prima dover crearla (credo) per default intendo una funzione standard propria di Python non che debbo scriverla io per poi andarla a richiamare, appunto come gli esempi che ho fatto prima per enumerate che ti fa un conteggio o lambda che lavora con variabili non create prima, entrambe fanno parte di Python come for while etc etc

ovviamente anche se credo che qualche sviluppatore di Python abbia pensato ad una cosa simile mi chiedo come mai non l'abbiano realizzata. invece di scrivere :


x=0

for etc etc

x+=1


y=0

while etc etc

y+=1

e così via per tante volte sopratutto nei codici lunghi dove a volte si ripetono tanti cicli, scrivere solo "incrementa(x)" dove incrementa fa tutto quello che faresti scrivendo x=0 per poi x+=1 solo che non si vedrebbe e non si ripeterebbero tante volte

ovviamente Ric non sto criticando Python e nessuno, sto solo facendo un ragionamento del perchè non esista già. giusto per parlarne e condividere un mio pensiero.
ragionandoci sopra ho pensato che forse probabilmente un problema potrebbe essere una questione di memoria?

nel senso che, x=0 e poi x+=1 a differenza di qualsiasi altro modo per ottenere ciò richiederebbe più memoria

e questo se non errò è un "problemino" che chi programma deve sempre tenere in considerazione

per le poche stringhe che uso io, no problem ma in determinati contesti è una cosa da valutare

ovviamente è solo una mia riflessione probabilmente infondata o non del tutto precisa


--- Ultima modifica di pypy in data 2018-11-04 15:29:34 ---
Abbi pazienza, quello che scrivi non ha senso (un po' anche in Italiano a dire il vero).


realizzare una funzione di "default" per incrementare una variabile senza prima dover crearla
Spero di aver capito più o meno che cosa intendi. Tu vorresti che Python avesse una funzione "incrementa_la_variabile_senza_crearla"? E da usare come? E soprattutto quale variabile?


Ragioniamo un po', ok? Se hai una variabile (collegata a un oggetto, ovviamente), è perché quell'oggetto e quella variabile *ti servono*, siamo d'accordo? Se scrivi:
>>> a = 10
lo scrivi perché l'oggetto "10" ti serve, e pertanto ne vuoi conservare un riferimento, per esempio nella variabile "a". Se non ti serve l'oggetto "10", basta solo non crearlo. Se vuoi incrementare l'oggetto "10" un paio di volte, puoi farlo. In ogni momento, l'oggetto resterà a tua disposizione per esaminarne il valore, incrementarlo ancora, o fare qualsiasi altra operazione ti venga in mente su quell'oggetto.


Invece quale sarebbe la tua idea di preciso? Quella di dire a python qualcosa tipo: "incrementa! incrementa! incrementa!" senza specificare nient'altro - e lui crea di nascosto un oggetto, NON ti dice qual è (nel senso che non hai in mano una variabile per raggiungere l'oggetto) e lo incrementa dietro le quinte ogni volta che tu dici "incrementa!"? E poi quando arriva il momento che vuoi verificare a che punto sei (cioè vedere in pratica quante volte hai detto "incrementa!") come fai? C'è una seconda funzione magica che si chiama "dimmi!" e ti dice il valore dell'oggetto nascosto? E se ci fosse questa funzione, allora che senso avrebbe tenere nascosto l'oggetto dietro le quinte? Tanto tu vuoi sapere quanto vale, no? E allora perché non crearlo, questo benedetto oggetto, visto che alla fine vedi bene che "ti serve"?

E poi, ancora: secondo te python dovrebbe avere la funzione "incrementa!"? Ma allora perché non anche un'altra funzione che si chiama "decrementa!"? E tu dai per scontato che parti a incrementare da 1, ma se volessi partire da 12? Facciamo una terza funzione "incrementa-da-12!"? E che cosa succede quanto vuoi tenere contemporaneamente DUE di questi "incrementatori" attivi? Facciamo una funzione "adesso-incrementane-un-altro!"? E poi "incrementa-il-primo!" e "incrementa-quell'altro!"?


Ma basta parlare, buttiamo giù un po' di codice, vuoi? Allora, ecco una implementazione molto semplice di questa tua idea:

>>> class _Incrementatore:
...   def __init__(self):
...     self.x = 0 # ecco il famigerato oggetto nascosto!
...   def incrementa(self):
...     self.x += 1
...   def dimmi(self):
...     return self.x
...
>>> i = _Incrementatore()
>>> incrementa = i.incrementa
>>> dimmi = i.dimmi
Immagina che Python, all'avvio, esegue di nascosto questo codice, dietro le quinte. A questo punto tu avresti disponibili due funzioni "incrementa" e "dimmi", da usare proprio come dici tu:

>>> incrementa()
>>> incrementa()
>>> incrementa()
>>> dimmi()
3
>>> incrementa()
>>> incrementa()
>>> dimmi()
5
>>> for i in range(5):
...   incrementa()
...
>>> dimmi()
10
Ora, capisci l'assurdità di questa cosa? Prova a rifarti le domande che ho fatto sopra, e confrontarle con questa roba. Se devi decrementare come fai? Se devi avere due o più incrementatori attivi come fai? Se vuoi partire da un numero diverso da 1 come fai? Eccetera eccetera... per ogni esigenza cosa fai, metti a disposizione una nuova funzione globale?
E tutto questo, naturalmente, quando ciò che basta fare è prendere un dannato oggetto, assegnarlo a una dannata variabile, e incrementarlo.


Ora, Python ha gli oggetti, e ha le variabili. Ha gli operatori per incrementare il valore di un oggetto. Ha strumenti per contare un set (se è quello che vuoi) e ha i generatori (se è quello che vuoi). Ha tutto quello che serve.


Capita di continuo, soprattutto per chi comincia, di fissarsi su un problema qualsiasi e chiedersi: ehi, ma se Python è tanto figo, perché non ha una soluzione già pronta proprio per questo problema su cui mi sto fissando adesso? Poi domani magari ti fissi su un altro problema e ti fai la stessa domanda per l'altro problema. Però occorre ragionare sulle cose, da un punto di vista generale. Il design di un linguaggio di programmazione non è la stessa cosa del design di uno specifico strumento per uno specifico compito.


Più chiaro così?



Ric però se ritieni di voler ragionare e parlare su un'argomento per me va benissimo l'ho aperto io il discorso, però non devi stravolgere ciò che ho scritto e credo che anche con gli esempi che ho fatto si è capito "bene" cosa intendessi.

io non ho detto che non si deve creare l'oggetto forse nella lettura hai sorvolato parti importanti dove specifico proprio che: "ovviamente dichiarare le variabile serve" oppure "funzione(y)" e quella "y" cosa dovrebbe essere, ma ovviamente la variabile che intendo inserire in quel determinato contesto che poi potrebbe essere "pippo" o altro quindi non c'è bisogno di creare nemmeno una funzione "dimmi()" per sapere a che punto è arrivato l'incremento perchè come è sempre stato basta digitare la variabile e ti ritorna il valore di "y" in questo caso oppure "pluto" o quello che vuoi, quindi il tuo esempio è sbagliato concettualmente in partenza perchè non dichiari nulla e se io volessi creare un altro incremento come saprebbe che non fa parte del primo se usando il tuo esempio non inserisci nulla nelle parentesi?

poi le problematiche che hai posto sono problematiche che già sono state risolte inserite nelle funzioni già dalle vecchie versioni di Python: vuoi che inizi da un numero diverso da dove vuoi prendere il codice per fare ciò da "range" oppure da "enumerate" o chissà quali altre funzioni ancora hanno questa possibilità quindi lo sai benissimo (meglio di me) che queste cose non sarebbero un problema risolverle perchè chi ha programmato Python questi codici li ha già fatti e come hanno realizzato ciò di sicuro non sarebbe un problema realizzare anche un decrementa come hai citato anche se qui poi la cosa l'hai di nuovo distorta perchè io l'esempio l'ho fatto usando i cicli "for e while" e la variabile si incrementava usando "x+=1" quindi in questo caso la variabile può solo incrementare.

in ultimo il codice che hai postato oltre ad a quanto ho detto sopra è un codice che fa le stesse cose di altri centinaia di codici di incremento che ho già trovato in rete e c'è ne sono veramente tantissimi e di tutti i tipi semplici o anche elaborati, quindi mi avrebbe fatto piacere, più leggere una tua opinione favorevole o meno ma specificando tecnicamente le tue motivazioni.

ps è vero che non è molto che ho iniziato con Python ma essendo che non è il mio primo linguaggio di programmazione, quindi non si tratta di un capriccio come hai inteso ma di una riflessione fatta prendendo spunto da alcune funzioni di Python che ho anche citato all'inizio del post tipo "enumerate" che ti incrementa un numero nel ciclo for oppure "lambda" che crea funzioni anonime.

Ok. Ma allora spiega che cosa vuoi in modo chiaro. Perché prima hai detto

realizzare una funzione di "default" per incrementare una variabile senza prima dover crearla
E se non crei la variabile, non puoi neanche sapere dopo qual è questa variabile, ti pare? E io ti ho fatto un'implementazione di quello che hai detto tu, e ovviamente è una implementazione assurda.


Adesso dici che questa cosa in effetti è assurda (bene) e che invece tu fin dal principio (non vedo dove ma poco male) dicevi che in realtà tu non vuoi... crearla questa variabile... ma vuoi comunque... saperla lo stesso dopo.

Uhm... ok suppongo. Non è difficile scrivere una implementazione, altrettanto assurda, di questa nuova cosa. Ma prima di scriverla, chiariamoci se è davvero la cosa che vuoi, oppure se intendi un'altra cosa ancora, e quale. Se ho capito bene, adesso tu vorresti qualcosa che funziona così:


>>> incrementa("x") # nota le virgolette...
>>> incrementa("x")
>>> x
2
>>> incrementa("y")
>>> y
1
Nota che non sarebbe possibile scrivere "incrementa(x)" perché appunto x non è mai stata creata esplicitamente. Ma possiamo dire a Python che vogliamo che il nome di quella variabile, che però NON vogliamo creare direttamente, sia "x". Ora, già se rileggi la frase che ho appena scritto ti rendi conto che stiamo proprio un po' andando nell'assurdo. Ma comunque, mettiamo pure di farlo. Le mie domande restano le stesse. Dobbiamo anche fare una funzione "decrementa" precostituita in python, perché magari un giorno scopri che anche decrementare è un lavoro molto comune? Che cosa succede se vuoi partire da 12 invece che da 0 o da 1? Che cosa succede se vuoi resettare il contatore? Eccetera.


poi le problematiche che hai posto sono problematiche che già sono state
risolte inserite nelle funzioni già dalle vecchie versioni di Python:
vuoi che inizi da un numero diverso da dove vuoi prendere il codice per
fare ciò da "range" oppure da "enumerate"
Anche qui non è chiaro che cosa intendi. Se quello che vuoi dire è: "range/enumerate sono molto più potenti e versatili della cosa che ho in mente io, ma comunque voglio ANCHE la cosa che dico io per default in Python", allora la risposta breve è: usa range/enumerate. Se invece quello che vuoi dire è "range/enumerate sono simili a quello che dico io", allora: no, assolutamente no. "Range" o "enumerate" non fanno quello che vorresti fare tu. "Range" produce in effetti un iteratore che a ogni ciclo assume un valore successivo: ma per usarlo devi assegnarlo a una variabile. La sua meccanica interna è simile (ma più complessa) all'esempio che ti facevo con il generatore. "Enumerate" è analogo ma cicla su un iteratore già esistente, come una lista. Quindi sono oggetti che in effetti puoi usare per "contare" e/o "incrementare". Ma la differenza con quello che vorresti tu è che comunque per usare questi oggetti devi crearli e assegnarli a una variabile. Non lavorano altrimenti.


Per chiarire ulteriormente: non è la parte "oggetto contatore" che manca in Python. Di "oggetti contatori" ce ne sono e/o ci sono gli strumenti per costruirne quanti ne vuoi, per gli usi più diversi. Quello che manca in Python è la parte "oggetto che uso senza associarlo a una variabile" (cioè, senza creare una variabile per esso).


E per chiarire ancora ulteriormente: quello che vuoi tu (chiamiamolo "contatore implicito") si può fare volendo (se però chiarisci esattamente che cosa intendi, e come si dovrebbe usare): ma il motivo per cui non esiste "di default" in Python è che non ha nessun senso voler usare, peraltro in modo limitato, un oggetto senza poterlo raggiungere con una variabile. Ci sono gli oggetti, e ci sono le variabili. Basta usarli. Per tornare al tuo esempio di partenza, come qualcuno ti ha fatto già notare, basta aggiungere all'inizio del tuo codice "x = y = 0" e tutto questo thread evapora all'istante.









Pagina: 1 2 3 Avanti



La discussione è chiusa.