Visualizza post

Questa sezione ti permette di visualizzare tutti i post inviati da questo utente. N.B: puoi vedere solo i post relativi alle aree dove hai l'accesso.


Post - Trizio

Pagine: [1] 2 3 4
1
Base / Re:List comprehension vs map e filter
« il: Dicembre 06, 2018, 16:57 »
Non ho mai letto il Lutz, davvero chiama/traduce i generatori con il termine "sequenza virtuale"? Perche' e' la prima volta che lo sento, e non mi pare una traduzione felice. Anche "sequenza fisica" mi sa di nuovo.

Nel capitolo "Iterations and Comprehensions" introduce il concetto di oggetti iterabili:

Citazione
The concept of "iterable objects" [...] has come to permeate the language's design. It's essentially a generalization of the notion of sequences—an object is considered iterable if it is either a phisically stored sequence, or an object that produces one result at a time in the context of an iteration tool like a for loop. In a sense, iterable objects include both physical sequences and virtual sequences computed on demand.

Qui e solo qui fa riferimento a map, zip e filter come sequenze virtuali.

Inoltre, sai che se anziche' usare delle parentesi quadre nella list-comprehension, metti delle parentesi tonde, diventa un generator comprehension?

Sì. Nel senso che ho intravisto la cosa nel pocket reference (i generatori sono affrontati più avanti). Ma... in effetti, mi hai messo una pulce nell'orecchio. Dal punto di vista delle performance, che differenza c'è tra generator expressions e map/filter?

Per quanto riguarda il cosa usare: dipende dall'idioma che usi nel tuo lavoro/azienda, e da come sei abituato a lavorare in altri linguaggi (ultimamente sta tornando di moda la functional programming --> map/filter/etc).
In generale in python si preferisce usare delle list comprehension perche' sono piu' "pulite" e piu' chiare per il pythonista medio.
Qui c'e' un bel thread su SO, con risposte interessanti e anche dei benchmarks: https://stackoverflow.com/a/1247490/

L'idea e' che se sull'oggetto che ti viene tornato devi fare delle operazioni (inserimento, manipolazioni varie), probabilmente conviene usare delle list-comprehension;
se devi solo iterarci, vai sempre di generatori/map/filter: sono molto piu' veloci (non devi mettere in memoria nulla -- e la memoria e' generalmente piu' lenta della cpu/cores). Inoltre non sempre puoi mettere tutta una lista in memoria (es. [a for a in range(10000000000)] probabilmente verra' killato dal tuo OS).

Dunque il vantaggio di map/filter è dato dal non sovraccaricare la RAM. Ma lo stesso si può ottenere in modo pythonico con una generator expression. O no?

2
Base / List comprehension vs map e filter
« il: Dicembre 06, 2018, 12:44 »
Una normale list comprehension:

>>> foo = [i * 10 for i in (1, 2, 3)]


Map:

>>> foo = map(lambda i: i * 10, (1, 2, 3))


List comprehension con if test:

>>> foo = [i for i in range(1, 11) if i % 2 == 0]


Filter:

>>> foo = filter(lambda i: i % 2 == 0, range(1, 11))


In Python 3, map e filter ritornano sequenze virtuali. Ora, se ho bisogno di una lista, il problema non si pone: mi conviene usare una list comprehension.

Supponiamo invece che io abbia bisogno solo di un iterable, non mi importa se una sequenza fisica o virtuale; in questo caso, quale approccio conviene? Il Lutz non è particolarmente chiaro. La list comprehension è veloce, perché ogni iterazione è eseguita alla velocità del linguaggio C (parole del Lutz, eh). map e filter, d’altro canto, creano sequenze virtuali che occupano la memoria poco alla volta. Se io ho una sequenza di oggetti particolarmente massiccia, suppongo che map e filter siano più convenienti.

3
Base / Re:Liste o altro?
« il: Novembre 29, 2018, 15:56 »
Anzi trovato

Player{"nome1":["gioco1","gioco2], "nome2":["gioco3","gico4"]}


Grazie grazie!!!!!

{'player1': ['gioco1', 'gioco2', ...], 'player2': ['gioco1', ...], ...}


Ma che ci devi fare con questa struttura dati? Perché se vuoi vedere quali giochi avete in comune potresti usare dei set anziché delle liste.

Ti conviene studiare da un buon manuale e basta. Già il fatto che stai pensando di usare le classi quando ancora non conosci i core data types mi lascia perplesso...

4
Base / Re:Augmented assignment e oggetti mutabili (WTF)
« il: Novembre 15, 2018, 16:29 »
Uhm, sì ma non vedo la domanda qui. O meglio, non vedo il problema. Se partiamo dal fatto che siamo consapevoli che
1) gli oggetti mutabili sono diversi dagli oggetti immutabili
2) le stesse operazioni su oggetti diversi possono avere una semantica diversa,
allora il resto, purché sia ben documentato, è una questione di gusti.

Non sono d'accordo. Quell'augmented assignment è di fatto una concatenazione sulle stringhe e sulle tuple; uno studioso poco attento potrebbe equivocare e pensare che faccia lo stesso con tutte le sequenze. A mio avviso è una palese incoerenza.

Inoltre, potrebbe indurre qualcuno a utilizzare questo espediente piuttosto che a utilizzare il metodo extend, ossia l'approccio più leggibile.

Per esempio, le liste. Partiamo dal fatto che sappiamo che a = a + [1] è una concatenazione e produce un oggetto diverso. A te dà fastidio che invece a += [1] sia un extend e quindi cambia l'oggetto sul posto. Perché ti sembra che quel "+=" dovrebbe richiamare di più alla mente una concatenazione. Curiosamente per me invece ha più un odore di "operazione da fare sul posto"... boh, sarò strano io. Certo non mi aspetto che a = 0; a += 1 cambi l'oggetto sul posto. Ma appunto, le stesse operazioni hanno una semantica diversa su oggetti diversi; una volta capito questo, tutti i discorsi "sarebbe meglio che A.foo si comportasse così e cosà per _analogia_ a quello che fa B.foo" sono legittimi, ma sono anche un po' questione di gusti. Probabilmente a scavare negli archivi di python-devs si trova anche la discussione e le motivazioni che hanno portato a mappare quel "+=" su extend... ma oggi la cosa importante è che sia documentato.
Poi naturalmente c'è che la concatenazione si può fare solo su liste, mentre extend accetta qualsiasi iterabile, e di conseguenza "+" e "+=" si comportano in modo diverso anche sotto questo aspetto. Ma di nuovo, se accettiamo la premessa (che concatenazione ed extend abbiano regole diverse) allora anche il "+=" non è difficile da accettare.
Forse l'errore "ottico" sta nel pensare che "+" e "+=" abbiano un "+" in comune... oppure di rifarsi sempre ad "a+=1" come scorciatoia per "a=a+1" ed aspettarsi che i due operatori implementino sempre la stessa "operazione analoga"... ma non è necessariamente una buona idea con gli oggetti più complessi degli interi. O piuttosto (ed è la mia umile opinione): è *sempre* una cattiva idea cercare di implementare operatori come "+=" con gli oggetti più complessi, e bisognerebbe sempre esplicitamente usare extend.

Sì, sono arrivato alla stessa conclusione. Ha un senso usarlo quando si lavora coi numeri, per esempio coi contatori.

Ma d'altra parte, chi ama insaporire il suo codice con un po' di sano offuscamento in stile perl, trova irresistibile scrivere a += 1, (il diavolo sta nella virgola). Contento lui.

A proposito, ieri ho scoperto un sistema per fare una shallow copy di una lista che è offuscamento allo stato dell'arte (modestamente):

>>> foo = [1, 2, 3]
>>> *bar, = foo     # oppure [*bar] = foo
>>> foo == bar
True
>>> foo is bar
False


Però qui utilizzo un extended sequence assignment per fare qualcosa di diverso dal suo scopo originario. Nel caso sopra è diverso.

Per i set, le cose stanno più o meno così, ma con una lieve differenza, che peraltro è ben documentata. L'operazione "|=" è effettivamente mappata su update, ma con la differenza che
Citazione
Note, the non-operator versions of union(), intersection(), difference(), and symmetric_difference(), issubset(), and issuperset() methods will accept any iterable as an argument. In contrast, their operator based counterparts require their arguments to be sets. This precludes error-prone constructions like set('abc') & 'cbs' in favor of the more readable set('abc').intersection('cbs').
(e, più sotto)
Note, the non-operator versions of the update(), intersection_update(), difference_update(), and symmetric_difference_update() methods will accept any iterable as an argument.
Questo potrà sembrarti una giustificazione ragionevole, oppure no. Io francamente prima di cinque minuti fa non mi ero neppure mai posto il problema, perché non ho mai usato "|=" nel mio codice (e continuerò a non usarlo)...

Anche qui... boh. Io sono dell'avviso che foo |= bar dovrebbe essere equivalente a foo = foo | bar. L'idea di avere un augmented assignment che si comporta in modo coerente dappertutto mi ispira di più.

5
Base / Augmented assignment e oggetti mutabili (WTF)
« il: Novembre 15, 2018, 12:09 »
L'augmented assignment (eh, non so come si chiami in italiano) con il + su una lista non esegue una concatenation, ma il metodo extend:

>>> foo = bar = [1, 2, 3]
>>> foo += 4, 5
>>> foo
[1, 2, 3, 4, 5]
>>> bar
[1, 2, 3, 4, 5]


Già qui la cosa mi urta, ma tant'è. Dato che l'operazione è mappata su extend e non su una concatenation l'oggetto a destra può essere qualsiasi iterable (nell'esempio una tupla) e ovviamente l'operazione cambia sul posto l'oggetto, conseguenza da tenere presente in caso di shared reference (come nell'esempio sopra).

Il tutto mi sembra sbagliato. E su più livelli. Tanto per cominciare il + fa pensare ad una concatenation ed infatti sarebbe lecito aspettarsi una concatenation. Inoltre, a che diavolo serve un in-place change così insaspettato, quando si può chiamare esplicitamente extend e rendere tutto molto più chiaro?

La cosa si fa ancora più oscura quando prendiamo i set. Ora, i set hanno i vari metodi update che possono cambiarli sul posto. Constatato come funziona l'augmented assignment con le liste, ci si potrebbe aspettare che un'operazione come |= sia mappata sul metodo update. Non proprio, come si evince qui:

>>> foo = bar = {'a', 'b', 'c'}
>>> foo |= 'x', 'y', 'z'
TypeError: unsupported operand type(s) for |=: 'set' and 'tuple'

>>> foo |= {'x', 'y', 'z'}
>>> foo
{'b', 'c', 'a', 'y', 'z', 'x'}
>>> bar
{'b', 'c', 'a', 'y', 'z', 'x'}


L'operazione di sicuro non esegue una normale unione (ossia foo = foo | {'x', 'y', 'z'}) dato che cambia l'oggetto sul posto (i.e. non ne crea uno nuovo come invece fa l'unione).  Ma non è neppure mappata sul metodo update, dato che update accetta qualsiasi iterable, mentre il qui presente augmented assignment accetta solo set. Il risultato è insomma una versione azzoppata del metodo update.




6
Base / Re:Aiuto per principiante
« il: Ottobre 21, 2018, 12:43 »
ma quello che era successo e' che ero abituato ad usare sti runner con il mio desktop environment (che ovviamente *non* poteva essere KDE o GNOME perche' quelli fichi usavano roba piu' primitiva a cui mancava un sacco di roba *ma* occupavano meno RAM e quindi ... boh, minchia non ho idea di cosa avessi in testa all'epoca.

In che senso?  :D

Quando ho cominciato a usare linux, due anni fa o poco più, ho installato LXDE, perché venivo da una brutta esperienza con gli OS a pagamento: il PC diventava sempre più lento a vista d'occhio. Poi sono passato a Openbox quando ho scoperto che potevo usarlo senza la suite di programmi LXDE, e di recente ho installato dwm, che è ancora più leggero (mi piacerebbe aggiungerci una funzionalità che apprezzavo in Openbox, il paging dei desktop virtuali—non saprei spiegarmi meglio—e in effetti sono quasi tentato dal comprarmi un manuale di C per implementarla io stesso). Insomma, a me sembra ragionevole che un DE non debba succhiare 200MB di preziosa RAM senza fare apparentemente nulla. Esigo che la RAM sia a mia completa disposizione, anche se non ne ho mai davvero bisogno. E' una condizione psicologica che rasenta i confini della patologia, ne sono consapevole, ma mi trovo bene.

Fracamente odio le interfacce grafiche per la stessa ragione (senza considerare il fatto che le trovo orribli—non si riesce a creare uno stile omogeneo che non rompa qualcosa neanche sbattendoci la testa ripetutamente... io uso il tema gtk di default perché francamente mi sono stancato di sbatterci la testa, just sayng). Se potessi navigare appena decentemente con Links o Lynx cestinerei Chromium senza battere ciglio.

Il colmo poi sono quei task manager con interfaccia grafica che consumano più risorse dei programmi che dovrebbero monitorare.  :D

7
Python-it.org cafè / Re:L'importanza delle prestazioni
« il: Ottobre 21, 2018, 11:24 »
Capisco. Bella risposta, Ric.

8
Python-it.org cafè / L'importanza delle prestazioni
« il: Ottobre 20, 2018, 11:29 »
Salve. Premetto di essere un principiante. E non intendo perseguire la carriera di ingegnere informatico. Insomma, le mie basi non sono granché solide e sospetto di avere qualche concezione distorta dell'informatica.

La mia idea di fondo (ossia quello che ho dedotto leggendo cose scritte da altri) è che un programma deve soddisfare le esigenze di chi lo usa, compiendo il minimo sforzo possibile in termini di risorse, e garantendo a chi lo legge e modifica il minimo sforzo possibile. Per un motivo o per l'altro, la questione delle prestazioni mi lascia un po' perplesso.

Non ho dimestichezza con altri linguaggi di programmazione (a dirla tutta non è che abbia una gran dimestichezza nemmeno con Python), ma stando a quanto ho capito ci sono linguaggi di programmazione decisamente più performanti. Perché utilizzare Python, quando verosimilmente è possibile utilizzare per lo stesso scopo -- a titolo di esempio -- C?

Presumo che un programma scritto in C possa tranquillamente soddisfare le esigenze dei customer, possa essere scritto in modo tale da essere leggibile, e a quanto pare è pressoché certo che sfonderà la barriera del suono.

Eppure il successo di Python sembrerebbe in qualche modo sbugiardare questo modello. Okay, un programma scritto in Python è verosimilmente più facile da mantenere rispetto ad un equivalente scritto  in C, ma le sue prestazioni dovrebbero essere comunque inferiori. Di poco, di molto...? Immagino dipenda da cosa faccia effettivamente quel programma.

Nel mondo vero, quanto sono davvero importanti le prestazioni?

P.S. Okay, sono ancora ingenuo, ma non del tutto sprovveduto. Immagino che nel "mondo vero" (ambito business, scientifico, ecc.) entri in gioco anche il fattore tempo, e che progettare un software in C sia più dispendioso in termini di tempo (e il tempo è denaro) rispetto a uno in Python. Poi, ovvio, è relativo...

9
Base / Re:String formatting
« il: Ottobre 16, 2018, 18:24 »
Ma perché?! Ripeto: sono due framework diversi per fare formattazione di stringhe. Non devono essere compatibili. Mica li devi usare insieme. E' come dire che ti secca che una view in Django si fa in un modo e in Flask in un altro.

Probabilmente sono io che voglio crearmi un problema che non esiste.

Sì ma non è che ci sia da capire. Basta leggere la documentazione, c'è scritto. E sì, per i float se non specifichi il formato non usa "qualcosa di simile a g", usa proprio "g". Così è scritto.

No. Nella documentazione c'è scritto "similar to 'g' (...)".

Sì però davvero, quando trovi tempo leggila questa benedetta documentazione. Format fa ben più di "aggiungere poche cose". Tra l'altro, Format è stato approvato con la PEP 3101 https://www.python.org/dev/peps/pep-3101, che ti consiglio anche di guardare e che ha anche dei link che rimandano ad approfondimenti. E tra l'altro, vedo adesso che la documentazione del "vecchio stile" ha un caveat all'inizio bello grosso: https://docs.python.org/3/library/stdtypes.html?highlight=sprintf#printf-style-string-formatting

Leggerò con più attenzione la documentazione, grazie.

10
Base / Re:String formatting
« il: Ottobre 16, 2018, 18:22 »
...

11
Base / Re:String formatting
« il: Ottobre 15, 2018, 18:03 »
> Perché?
E' un'asimmetria. Ovviamente capisco la ragione, ed è giusto così. Ma resta sempre un piccolo inciampo cognitivo. Non dico che non ci dormo la notte, eh.

In che senso è un'assimetria?

> mi seccava il fatto che il comportamento cambiasse a seconda dell'approccio scelto.
No, non hai capito. Non cambia il comportamento, è che proprio sono due cose diverse. String.format() ha a che vedere con la *rappresentazione* di un numero, non con le operazioni di casting. Con format() tu puoi specificare la precisione della rappresentazione di un numero decimale, ovvero quanti decimali ci vuoi mettere. Certo che poi, come caso limite, se dici che vuoi "zero decimali", allora a lato pratico quello che "sembra", quello che vedi, è un intero. Ma è un intero che risulta da una scelta di precisione nella rappresentazione, *quindi* da un arrotondamento. Il comportamento di format() è lo stesso che impostare una precisione in decimal.Decimal.
D'altra parte, int() è un casting e non c'entra niente con la precisione. Fare int() *non* vuol dire "dammi una precisione di zero decimali", vuol dire "converti il tipo". Ora, int(x) significa "la parte intera di x", quindi non devi stupirti se a lato pratico tu vedi il tuo intero troncato.

Ora, quale delle due operazioni in realtà desideri, questo devi deciderlo tu:
1) "voglio rappresentare questo float come stringa, con una precisione di zero decimali, il che coincidentalmente farà sembrare un intero questo risultato di un arrotondamento".
2) "voglio castare questo float a intero (cioè troncarlo), e quindi rappresentarlo come stringa".
Tu pensi che siano la stessa cosa concettualmente, ma con due approcci diversi, e ti annoia che possano dare risultati diversi. Ma in realtà sono due cose concettualmente diverse, ed è normale che gli approcci e i risultati siano diversi.

No, probabilmente mi sono spiegato male. Quando parlavo di approcci diversi mi riferivo all'espressione % e al format method. Mi secca che la stessa operazione mi ritorni un risultato in un caso e un errore nell'altro.

> Avevo già letto. Il punto è che l'output di un intero è sempre in base 10.
Quindi no, non avevi letto.

>>> '{:d}'.format(14)
'14'
>>> '{:x}'.format(14)
'e'
>>> '{:o}'.format(14)
'16'
>>> '{:b}'.format(14)
'1110'


Ma io non mi lamento di 'b', 'o' e 'x'. Mi lamento di 'd'.  L'output di un intero è sempre in base 10:

>>> 0b1
1
>>> 0o1
1
>>> 0x1
1


>>> '{}, {}, {}'.format(0b1, 0o1, 0x1)
'1, 1, 1'


Quindi ancora mi sfugge l'utilità di 'd'. A meno che in quest'ultima sessione Python non mi schiaffi di nascosto un 'd' come type code di default (perché magari è così che funziona internamente).

Ah, forse ho capito. Credo che quando si usa format Python internamente guarda il type dell'argomento e in assenza di un type code fa sì che la rappresentazione avvenga in un certo modo. Tipo, se l'argomento è una stringa, usa 's'; se l'argomento è un intero, usa 'd'. Se l'argomento è un float, usa... qualcosa di simile a 'g'. Non capisco però come funzioni con altri oggetti, tipo sequenze, complex... boh.

> print abbia sfasciato un bel po' di codice. Tanto valeva cambiare anche lo string string formatting...
Sono cose diverse. Print è la stessa operazione che ha cambiato implementazione e (non troppo) semantica. L'interpolazione di stringa con il vecchio % e la nuova con format sono approcci diversi per coprire (parzialmente) lo stesso problema. Tra l'altro, a lato pratico, la transizione di print si può gestire automaticamente nella maggior parte dei casi con 2to3. La formattazione di stringa mica tanto.

Ah. Quindi a che è servito introdurre format? Le poche cose che aggiunge non mi sembra siano così difficili da implementare da soli. Avere due strumenti diversi per fare lo stesso lavoro francamente mi sembra solo fonte di confusione. Alla fine penso ci sia gente che è abituata a usare o solo l'espressione %, o solo format; col risultato che ovviamente tutti devono sapere come funzionano entrambi. Fattibilissimo; ma se nel fare la stessa cosa uno strumento mi restituisce un risultato accettabile e l'altro un errore...

12
Base / Re:String formatting
« il: Ottobre 15, 2018, 16:10 »
A te da noia che non si possa fare '{:d}'.format(1.0), a me da fastidio l'inverso, che *si possa* fare '{:f}'.format(1)...

Perché?

> 1) Devo per forza eseguire la conversione manualmente?
Se vuoi puoi farlo, ma un conto è castare un float a int e poi rappresentarlo come stringa, un conto rappresentare a stringa un float specificandone la precisione. Nota che oltretutto i due sistemi seguono regole di arrotondamento differenti. Quello che probabilmente stai cercando è la seconda che ho detto, e sarebbe
>>> '{:.0f}'.format(1.6)
'2'

e come forse già hai visto, invece
>>> int(1.6)
1

che può essere (o no) quello che vuoi...

Non è che la cosa mi servisse davvero, ho notato solo ora l'arcano mentre ripassavo format e giocherellavo con la console.  :D
In effetti non trovo particolarmente utile l'arrotondamento verso zero... mi seccava il fatto che il comportamento cambiasse a seconda dell'approccio scelto.

> 2) Perché? A che diavolo serve il type code 'd' se non converte una cippa lippa?
Ehm. Come vedi, a qualcosina serve. Comunque c'è sempre la documentazione, eh: https://docs.python.org/3/library/string.html#formatspec

Avevo già letto. Il punto è che l'output di un intero è sempre in base 10.

> 3) Perché l'espressione e format devono convivere? Retrocompatibilità? Ha un senso per python2, non per python3.
Ha senso anche per python3, visto che un mucchio di codice è stato portato senza problemi proprio perché py3 conserva cose di py2.

Sempre restando in argomento stringhe, suppongo che print abbia sfasciato un bel po' di codice. Tanto valeva cambiare anche lo string string formatting, così da non dover costringere le persone ad imparare due approcci diversi che risolvono lo stesso problema. O no?

PS: Ah, e non hai ancora incontrato le f-string, suppongo... https://docs.python.org/3/reference/lexical_analysis.html#f-strings  ;)

Urgh. No.

13
Base / String formatting
« il: Ottobre 15, 2018, 13:42 »
Salve. Domande banali. Python 3.5.

Quando nell'espressione passo un float al type code 'd', nella stringa risultante ottengo un intero (i.e. quello che mi aspetto):

>>> '%d' % 1.0
'1'


Quando faccio la stessa cosa con format ottengo un errore:

>>> '{:d}'.format(1.0)
ValueError: Unknown format code 'd' for object of type 'float'


I type code 'f', 'e' e 'g' accettano interi, sia con l'espressione che con format:

>>> '%f' % 1
'1.000000'

>>> '{:f}'.format(1)
'1.000000'


1) Devo per forza eseguire la conversione manualmente?

>>> '{:d}'.format(int(1.0))
'1'


2) Perché? A che diavolo serve il type code 'd' se non converte una cippa lippa?

3) Perché l'espressione e format devono convivere? Retrocompatibilità? Ha un senso per python2, non per python3.

14
Beh, la cosa mi sorprende perché mi pare strano che non abbiano pensato ad una cosa del genere, dato che giustappunto non sono una charity. Non me ne intendo, ma presumo ci siano modi più efficienti per bloccare l'accesso agli scrocconi. Inoltre, la cosa me le fa un po' girare perché mia madre l'abbonamento lo ha pagato.

EDIT: mmm...


15
Salve. Ultimamente mi sono un po' scocciato della pubblicità online e ho cercato un metodo alternativo ai vari ad-blocker di Firefox. Ho dunque provato ad usare il browser Links, per vedere se potevo rimpiazzare direttamente Firefox. Come soluzione al mio problema non è un granché  e alla fine ho optato per pi-hole installato sul mio raspberry.

Il fatto è che incidentalmente ho scoperto che Links sembrerebbe aggirare il paywall del Washington Post. È il caso di avvisarli?

Pagine: [1] 2 3 4