Category Archives: Python

NumPy – 1 – oltre Python

nikon-small-world-ammonite-shell
Inizio (come annunciato qui) con Python Data Science Handbook di Jake VanderPlas. In particolare seguo (ahemmm… copio) la Jupyter notebook version. Mi sembra che Jake lo consenta, Jake rockz! 😀 e allora sono pronto per iniziare, qui: IPython: Beyond Normal Python.

Partiamo dall’inizio, dice, io uso IPython e un text-editor.
L’editor che usa Jake è più lussuoso di quello che uso io —gedit— e se posso non lo cambio, per ragioni di compatibilità con i miei contatti e poi perché sono vecchio e ai miei tempi l’editor faceva solo l’essenziale; prima del vi.

Invece come ambiente (environment, quello che io chiamo di solito REPL) Jake usa e raccoanda IPython, mi adeguo, anche perché sì rockz! 😀

IPython is about using Python effectively for interactive scientific and data-intensive computing. This chapter will start by stepping through some of the IPython features that are useful to the practice of data science, focusing especially on the syntax it offers beyond the standard features of Python. Next, we will go into a bit more depth on some of the more useful “magic commands” that can speed-up common tasks in creating and using data science code. Finally, we will touch on some of the features of the notebook that make it useful in understanding data and sharing results.

IPython può essere usato in due modi, shell e notebook; prendere quell più conveniente caso per caso, intanto vediamoli.

Lanciare la shell di Ipython
This chapter, like most of this book, is not designed to be absorbed passively. I recommend that as you read through it, you follow along and experiment with the tools and syntax we cover: the muscle-memory you build through doing this will be far more useful than the simple act of reading about it. Start by launching the IPython interpreter by typing ipython on the command-line.
C’è anche l’help, sempre di Jake: Help and Documentation in IPython.
Siccome scrivere ogni volta ipython sarebbe troppo lungo, anche perché al solito io lo faccio con opzioni, prima di subito mi sono creato l’alias:

np0

sì, lo so, ho qualche settaggio non a posto –who cares. E anche

np1

e così via 😀

Lanciare il Jupyter Notebook
The Jupyter notebook is a browser-based graphical interface to the IPython shell, and builds on it a rich set of dynamic display capabilities. As well as executing Python/IPython statements, the notebook allows the user to include formatted text, static and dynamic visualizations, mathematical equations, JavaScript widgets, and much more. Furthermore, these documents can be saved in a way that lets other people open them and execute the code on their own systems.

np2

Figo Fine, ma sapete io sono vecchio, solitario, per adesso so che c’è poi chissà… Le previsioni riguardo al futuro… (inizio-cit).

OK, per oggi basta. Anche perché –sapete– c’è sempre il rischio 😉
:mrgreen:

NumPy – inizio, sarà lunga – 0

numpy_logoUn amico prof al Poli, qualche anno più di me, me l’aveva consigliato caldamente quando stavo per partire con la telenovela Octave mi aveva kwasy sgridato: “vai su MatPlotLib!”. Per fortuna che gli esami al Poli li avevo finiti, da tempo 😀
E ora — forse — chissà — probabilmente…

Devo scegliere un testo da seguire, ci sono diversi candidati:

Rougier da per scontato cose; non riesco a far girare gli esempi che ho provato perché mancano moduli e non ho capito quali. Per esempio che differenza c’è tra i vari timeit? Peccato perché sembra bello. Uh! timeit è in tkinter, scoperto leggendo Jake.
Ha una ricca bibliografia, articoli e libri (per lo più non online).

Jake –lo seguo da sempre sui social– sembra ottimo.
Di Jake c’è anche A Whirlwind Tour of Python, da considerare.

Aaron Meurer e Ondřej Čertík (anche lui presente nel paper) sono i principali artefici di Sympy.

Allora, dopo una scorsa, provando a campione alcuni script mi sembra che sia possibile partire seguendo Jake Vanderplas. Sarà una serie di post quasi solo per me, per vedere come fanno i nerds (über) per cercare di superare il mio stato di aspirante n00b 😉
Non è detto che finisca ma ci provo. mettendocela tutta 😀
Intanto sto facendo altro, completamente differente. Ma questo non lo racconto (per adesso) 😉

:mrgreen:

SICP in Python

nikon-small-world-glycerin-based-soapy-solution
Cosa non si trova ontehtoobz!
Recentemente José Alonso posta questo cinguettio: SICP (Structure and Interpretation of Computer Programs) in Python.
Non è una novità assoluta, l’ho anche inserito nella pagina dei manuali di OKp: Composing Programs.
Ma siccome SICP è uno dei miei tormentoni preferiti oggi guardo e riferisco. Viene da uno corso (uno di quelli iniziali) per gli informatti, giù a Berkeley. Seguendo i link si trovano cose interessanti, p.es.:

This semester, 61A will be taught using the Python 3 programming language. Python is a popular language in both industry and academia. It is also particularly well-suited to the task of exploring the topics taught in this course. It is an open-source language developed by a large volunteer community that prides itself on the diversity of its contributors.

In previous semesters, this course was taught using the Scheme language, a dialect of Lisp, which itself dates back to 1958, making it the second-oldest “higher-level” programming language that is still in use (after Fortran). Lisp and Python are similar in many ways. In fact, Lisp popularized many of the features that make Python a great language. Python has excellent library support for a vast range of application areas. Knowing Python will help you pursue your future programming interests, wherever they may lead you.

E anche

Learning Cooperatively
With the obvious exception of exams, we encourage you to discuss all of the course activities with your friends and classmates as you are working on them. You will definitely learn more in this class if you work with others than if you do not. Ask questions, answer questions, and share ideas liberally.

Since you’re working collaboratively, keep your project partner and TA informed. Questa è scontata ma forse –OK, perso[nale], non leggete il mio commento.

Cooperation has a limit, however, and in 61A that limit is code. Homework problems should be completed and turned in individually. Feel free to discuss the problems with others beforehand; just submit your own work in the end. Parole sante! valgono anche per me quando affronto gli esercizi di SICP.

Copying all or part of another person’s work [… is a form] of cheating and will not be tolerated.

Rather than copying someone else’s work, ask for help. You are not alone […]!

Peccato non essere un giovane pischello californiano! 😦

OK, ma il manuale?
Non l’ho esaminato in dettaglio; non ho fatto gli esempi proposti (anche perché mi sembrano chiari e non sono difficili, almeno all’inizio).
Per non auto-spoilerarmi (ahemmm… a volte seguo la moda della post-truth) non sono andato oltre al cap. 1. Nel PDF c’è qualche codice HTML che è rimasto invece di essere interpretato, ma sono pochissimi e facili da sgamare.
Segue abbastanza fedelmente l’originale in Scheme, in qualche punto è aggiornato; in qualche punto Python impone di scostarsi, comunque è fatto bene.

Forse per quanto detto nell’intro al corso (e da me riportato sopra) mancano gli esercizi che il SICP originale propone.

Mi sembra usabile per imparare sia la programmazione (un po’, mica tutto) sia Python (un po’, mica tutto). E gli esercizi mancanti andate a recuperarli di là e fateli. Io invece continuo per la vecchia via, sono vecchio e abitudinario.

Anche se c’è sempre il solito rischio.

:mrgreen:

Traduzioni da un linguaggio a un altro – 2

system76

Il titolo è fuorviante ma è quello per via che sto continuando a qui.
Ho semplificato troppo parlando del passaggio dei parametri a funzione; dando la colpa al Fortran che passa tutto per indirizzo ho messo su questo esempio:

*     main
      n = 5
      call foo(n, nq)
      print *, n, nq
      call foo(n, nq)
      print *, n, nq
      call foo(n, nq)
      print *, n, nq
      end
      
      subroutine foo(k, l)
      k = k + 1
      l = k ** 2
      end

pass

che con Python può diventare

def foo(k):
      k = k + 1
      l = k ** 2
      return l

#  main
n = 5
nq = foo(n)
n += 1
print(n, nq)
n += 1
nq = foo(n)
print(n, nq)
n += 1
nq = foo(n)
print(n, nq)

py-pass2

Però non è sempre così semplice! 😦 Sono stato richiamato, redarguito e allora tento di rimediare.
Inoltre il caso è più generale, non riguarda solo le traduzioni tra linguaggi.

Invece di rifare l’esempio precedente eccone uno nuovo. Secondo me l’esempio dev’essere il più piccolo possibile, eliminare tutto quanto non strettamente necessario; ovvio che poi risulti banale.
Ne approfitto per trattare anche il caso degli arrays; in realtà con Python forse sono meglio le liste. Questione che meriterebbe più attenzione, p.es. ecco i primi due risultati alla query a Stack OverFlow: uno e due.

Supponiamo di avere una serie di dati di temperature relative al processo [fate voi, non sono tanto bravo a inventare]. Purtroppo la macchina è ‘mericana e usa i gradi fahrenheit, quelli che usano solo loro (e, purtroppo, usano solo quelli). Devo inoltre calcolare il valore medio (e in un caso più realistico scarto quadratico e altri valori ancora, l’esempio dev’essere semplice). Ecco come –secondo me– si può fare in modo semplice.

def conv(f):
    return round((f - 32) * 5 / 9, 1)

def celsius(a):
    n = 0
    for c in a:
        a[n] = conv(c)
        n += 1
    media = round(sum(a) / len(a), 1)
    #print(a)
    #print(media)
    r = [a, media]
    return r

#main
t = [120, 110, 112, 125, 113, 117, 109, 121]
retval = celsius(t)
#print(retval)
tc = retval[0]
media = retval[1]
print("temperature:", tc)
print("media: ", media)

f2c

Ho lasciato commentate le print() provvisorie, di debug.

Ma un pythonista serio non scriverebbe mai codice come quello 😦 c’è la list comprehension, più chiara, compatta ed efficiente, ecco la nuova versione (il nuovo è indicato con il commento # ****):

def conv(f):
    return round((f - 32) * 5 / 9, 1)

def celsius(a):
    a = [conv(n) for n in a]           # ***
    media = round(sum(a) / len(a), 1)
    #print(a)
    #print(media)
    r = [a, media]
    return r

#main
t = [120, 110, 112, 125, 113, 117, 109, 121]
retval = celsius(t)
#print(retval)
tc = retval[0]
media = retval[1]
print("temperature:", tc)
print("media: ", media)

:mrgreen:

Traduzioni da un linguaggio a un altro

btf3

Un discorso che devo prendere un po’ alla lunga, da lontano, roba di prima di voi giovani, ma poi arrivo al dunque, cioè all’oggi, promesso.

In Fortran Ï€, pi, il rapporto tra le misure della circonferenza e il raggio non è definito. Ma tutti sanno che l’arcotangente di 1 rad vale Ï€/4.
E allora diventa tutto semplice, gli antichi (non gli antichissimi ma non cambia molto) usavano il Fortran 77 (1978).
Vediamo se ricordo bene perché possono esserci diversi modi di scrivere, tenendo presente che i tipi sono impliciti e allora

      pi1 = 4.0 * atan(1.0)
      pi2 = 4.0 * atan(1)
      pi3 = 4 * atan(1.0)
      pi4 = 4.0 * datan(1.0)
      
      print *, pi1, pi2, pi3, pi4
      end

ap0

Partito molto male: 2 errori –no uno solo in 2 varietà– correggo.

La riga pi2 = 4.0 * atan(1) è irrecuperabile, a correggerla diventa uguale alla precedente.
La riga pi4 = 4.0 * datan(1.0) è più intrigante. Intanto la D iniziale sta per double precision, quello che in C si chiama double.

      pi1 = 4.0 * atan(1.0)
      pi3 = 4 * atan(1.0)
      pi4 = 4.0 * datan(1.d0)
      pi5 = 4.0d0 * datan(1.d0)
      pi6 = 4.0d0 * datan(dble(1.0))
      
      print "(f12.10)" , pi1, pi3, pi4, pi5, pi6
      end

ap1

OK, ottengo gli stessi valori. Notare la promozione a double nella moltiplicazione per il calcolo di pi4. Notare anche la funzione dble, cast a double direbbe il C-ista.

Ma non va come previsto: otteniamo sempre lo stesso numero di cifre corrette, sia usando i real*4 che i real*8 corrispondenti a float e double del C.
Devo dichiarare il tipo quando non rientra in quelli di default. Infatti questo viene automaticamente assegnato a integer (2 bytes nel Fortran IV, 4 nel 77) se la prima lettera della variabile è nell’intervallo [I-N], real*4 per tutte le altre. Si ricorda inoltre che al di fuori delle stringhe quotate si ha una conversione automatica al maiuscolo.
Ecco:

      double precision pi4
      real * 8 pi6

      pi1 = 4.0 * atan(1.0)
      pi3 = 4 * atan(1.0)
      pi4 = 4.0 * datan(1.d0)
      pi5 = 4.0d0 * datan(1.d0)
      pi6 = 4.0d0 * datan(dble(1.0))
      
      print "(f12.10)", pi1, pi3, pi4, pi5, pi6
      end

ap2

OK 😀 Ah! dimenticavo: gli spazi non sono significativi, real*8 e real * 8 sono sinonimi, lo sarebbe pure r e a l * 8.

Lo so che nessuno usa più il Fortran, neanch’io, ma devo raccontare questo altrimenti poi non si capisce.

Neanche e, quella di Euler, dei logaritmi naturali, è predefinita. Ma facciamo come per π:

      real * 8 e2

      e1 = exp(1.0)
      e2 = dexp(1.d0)      

      print "(f12.10)", e1, e2
      end

ae

OK 😀 notare che al posto di 1.0 posso scrivere 1. come posso scrivere .1 per 0.1; i vecchi lo facevano sempre.

Finora niente di sconvolgente ma ecco un passo ancora

      e = exp(1.0)
      pi = 4.0 * atan(1.0)
      ie2 = 2 * e
      ipi2 = 2 * pi
        
      print *, e, pi
      print *, ie2, ipi2
      end

app

OK, i cast a integer*4 tronca i real*4. Ma attenzione, questo avviene –ovviamente– dopo la moltiplicazione. Ovviamente è diverso da questo caso:

      e = exp(1.0)
      pi = 4.0 * atan(1.0)
      ie = e
      ipi = pi
      ie2 = 2 * ie
      ipi2 = 2 * ipi
        
      print *, e, pi
      print *, ie2, ipi2
      end

iapp

Se si vuole l’arrotondamento all’intero più vicino ci sono due modi:

      e = exp(1.0)
      ie1 = e + 0.5
      ie2 = int(e + 0.5)
      ie3 = nint(e)

      print *, ie1, ie2, ie3
      end

round

Siccome la conversione da real a integer avviene automaticamente per troncamento i vecchi usavano sommare 1/2 al valore da convertire. La funzione int() in questo caso è implicita per ie1 e esplicita per ie2. Esiste la funzione di arrotondamento nint() ma è usata raramente (mai).

Finora ho barato; no, non barato ma omesso di dire tutta la verità. Alcune funzioni intrinseche del Fortran sono da sempre (OK, quasi) polimorfe.
Già vista datan() ma risulta più chiaro con la funzione max():

      m1 = max(3, 1, 4, 1, 5)
      m2 = max0(3, 1, 4, 1, 5)
      m3 = max1(3.0, 1.0, 4.0, 1.0, 5.0)
      rm2 = amax0(3, 1, 4, 1, 5)
      rm3 = amax1(3.0, 1.0, 4.0, 1.0, 5.0)
      print *, m1, m2, m3
      print *, rm2, rm3
      end

fsp

Sì, conta la lettera iniziale (A per i real, D per i double) e l’eventuale numero finale (0 per integer, 1 per real). Come se non fosse abbastanza ci sono state variazioni (tante) tra le versioni 77 e 90 (e successive), RTFM (cit.).

Ci sarebbe da raccontare molto su common ma salto.
Come pure salto tutto il capitolo sulle matrici, c’è Octave visto recentemente.

Invece una cosa sempre in agguato: il passaggio di variabili ai sottoprogrammi. In Fortran ci sono le function, funzioni come quelle di C e Python e quasi tutti i linguaggi. Ma ci sono anche le subroutines –anzi sono nate prima– sottoprogrammi chiamate con la keyword call che non ritornano un valore come le funzioni ma modificano i dati passati. Tutti, perché vengono passati per indirizzo (questo è vero solo per le versioni non nuovissime ma il codice è spesso piuttosto attempato). Un esempio minimo:

*     main
      n = 5
      call foo(n, nq)
      print *, n, nq
      call foo(n, nq)
      print *, n, nq
      call foo(n, nq)
      print *, n, nq
      end
      
      subroutine foo(k, l)
      k = k + 1
      l = k ** 2
      end

pass

Sembra facile, traduco in Python:

### versione iniziale, non funziona

def foo(k, l):
      k = k + 1
      l = k ** 2

#  main
n = 5
foo(n, nq)
print(n, nq)
foo(n, nq)
print(n, nq)
foo(n, nq)
print(n, nq)

py-pass

Ehmmm… no; non basta aggiustare la sintassi delle singole righe. Il valore di l | nq dev’essere ritornato espressamente. Inoltre è inutile passarlo tra gli argomenti:

### ancora non funziona

def foo(k):
      k = k + 1
      l = k ** 2
      return l

#  main
n = 5
nq = foo(n)
print(n, nq)
nq = foo(n)
print(n, nq)
nq = foo(n)
print(n, nq)

py-pass1

No! non ci sono ancora: ovvio, gli passo sempre lo stesso parametro n = 5; la modifica all’interno di foo() è locale e in main non viene vista, correggo:

def foo(k):
      k = k + 1
      l = k ** 2
      return l

#  main
n = 5
nq = foo(n)
n += 1
print(n, nq)
n += 1
nq = foo(n)
print(n, nq)
n += 1
nq = foo(n)
print(n, nq)

py-pass2

OK! ma il codice è orrendo! Non voglio vedere niente di simile 😦

Come visto anche per un caso molto banale la traduzione automatica, riga per riga non è possibile. Ci sarebbe da dare la colpa al fortrainer che se avesse fatto le cose per bene… scrivendo la subroutine foo() così:

      subroutine foo(k, l)
      j = k + 1
      l = j ** 2
      end

la variabile k sarebbe stata solo di input –o anche intent(in) per le versioni nuove del Fortran– non sarebbe ritornata modificata e il main avrebbe dovuto essere scritto meglio.

Adesso provate –Gedankenexperiment– ad applicare questo a codice reale 👿 Ma secondo me va fatto. Prima o poi. Non necessariamente da me.
:mrgreen:

Valutare XKCD con Windows? Si può fare!

nm0

Nel post precedente si valutava l’ipotesi che XKCD sia collegato a La Risposta, come –forse– un giorno grazie all’AI si riuscirà finalmente a provare, trovando –finalmente– La Domanda.
Nel post precedente (devo ricordarmi di non cominciare una frase nello stesso modo della precedente) eravamo in un ambiente adatto con tutti i tools che possono tornare utili disponibili e pronti fin da subito, anzi da prima (quando ero ggiovane ricordo che un giorno è arrivato UNIX (allora si scriveva così, tutto maiuscolo e bisognava dire che UNIX is a trademark of Bell Laboratories, Inc.)) ma come e cosa si può fare in ambienti meno friendly amichevoli. O –a volte– decisamente ostili, per esempio quello con la finestra storta, com’è già che si chiama?

Anche per loro ci sono strumenti [1] grazie a FOSS, come vedremo.
Oggi useremo Python, 3.x, costruendo il comando passo-passo.

x6

Fin qui niente di speciale, è una stringa. Per il nostro scopo possiamo usare list():

x7

Dalla lista c possiamo passare a quella dei valori ASCII (o Unicode, in questo caso coincidono) v.

x8

Lo so che non si devono fare cicli in questo modo [2] ma è provvisorio, solo per la costruzione.
Usiamo la funzione ord().
Abbiamo così la lista dei valori; troppo grossi però. Dovrebbe valere 1 per A, 2 per B e così via.
Beh, facile basta applicare un offset, questo:

x9

e riscrivere il loop precedente così:

x10

Non ci resta che fare la somma, via sum():

x11

OK! Adesso l’unione degli snippets [3] precedenti ed ecco:

x12

Resta un ultimo step: [4]

x13

Fatto! In fondo era semplice [5] 😀


[1] Mi dice Sole (sì, è tornata) che non devo usare “tools”; e non fare i prulari.
[2] prima vennero per il GOTO ma non era per me, poi vennero per… (quasi-cit.).
[3] frammenti, mi dicono.
[4] passo. (Devo smetterla che si sta –come dire– potrebbe diventare pericoloso per me e per il ‘puter).
[5]
mom:mrgreen:

str2lst: omoiconicità in Python

timpo

Intanto la definizione della parola difficile che non sono nemmeno tanto sicuro ci sia in italiano: omoiconicità.
La Wiki (come farei senza? (auto-cit.)) dice:

In computer programming, homoiconicity (from the Greek words homo meaning the same and icon meaning representation) is a property of some programming languages in which the program structure is similar to its syntax, and therefore the program’s internal representation can be inferred by reading the text’s layout.

I linguaggi che vengono in mente prima di subito sono quelli della famiglia del Lisp ma non lo dico per non spaventare.

E poi anche perché mi serve con Python.
Forse non ho stackoverflato e googlato bene, ma in fondo è una cosa semplicissima:

s0

OK, funziona, da farci la funzione:

def str2lst(st):
    return eval(st)

s1

OK, ma visto che è così sintetica forse non serve, usare direttamente eval. Anche perché se uno proprio vuole (voglio? sì!) c’è lambda:

str2lst = lambda st: eval(st)

s2

OK! 😀
Forse ne ho già parlato in passato ma non riesco a ritrovarlo. E i fatti di questi giorni mi hanno bloccato su questa funzione semplicissima. Non vorrei dire che sia tutta colpa di Trump ma insomma… :mrgreen:

Coconut – utilities e considerazioni conclusive – 13

super-metal

Proseguendo da qui oggi copio qui, dove si parla di utilities. E poi concludo (per adesso).

Syntax Highlighting
Si può fare con Sublime Text, Pygments o altri metodi ancora.
Interessa? Pygments mi sembra sexy; non fosse che sono vecchio e per via di quello che adesso racconto.

Si può usare Coconut?
Secondo me sì ma ci sono alcune issues da addressare questioni da affrontare:

  • Coconut è nuovo e (per quel che ne so) personale, sviluppato dal solo Evan Hubinger, rockz 😀
  • sarebbe un altro linguaggio da imparare, sono già troppi;
  • per ragioni misteriose i linguaggi funzionali sono visti con diffidenza.

Illustro con un paio di esempi, spero indicativi.

c59

Quale delle due scritture è più naturale? Forse solo questione di abitudini ma…

Inoltre supponiamo che il codice Coconut sia contenuto nel file e.coco:

from math import exp
1 |> exp |> print

che compilo

c60

Il file risultante e.py è OK, nel senso che può essere eseguito

c61

ma è disastrosamente lungo e casinato

c62

Aprendolo e copiando le ultime due righe dentro Python (cosa che potrebbe capitare in caso di manutenzione, se si evita il file Coconut) si ottiene un codice eseguibile:

c63

quasi. Un caso più realistico (anche se sempre finto) è quello in cui il file .coco sia un modulo, come nel caso minimo val_const.coco:

from math import exp

def val_e():
    match t = 1 |> exp
    return t

che posso compilare e usare con Python:

c64

OK. Però, al solito il codice .py prodotto è lungo

c65

e –soprattutto– immodificabile all’interno di Python, per la manutenzione serve Coconut.

Quindi, in conclusione: Coconut mi piace, da monitorare, vedere se cresce. Per l’uso è da valutare all’interno del proprio ecosistema (cit.), è un altro linguaggio il cui apprendimento richiede risorse.
Mi è inoltre stato fatto notare che esistono progetti simili, chissà l’evoluzione… (visto che non cito Niels Bohr?) 😀

:mrgreen:

Coconut – built-ins – 12

Coj9

Continuo da qui, oggi su built-ins che semplificano il codice, qui.

addpattern
Takes one argument that is a pattern-matching function, and returns a decorator that adds the patterns in the existing function to the new function being decorated, where the existing patterns are checked first, then the new. Equivalent to:

def addpattern(base_func):
    """Decorator to add a new case to 
       a pattern-matching function, 
       where the new case is checked last."""
    
    def pattern_adder(func):
        def add_pattern_func(*args, **kwargs):
            try:
                return base_func(*args, **kwargs)
            except MatchError:
                return func(*args, **kwargs)
        return add_pattern_func
    return pattern_adder

c48

cosa che con Python … ahemmmm, già 😉

prepattern
Takes one argument that is a pattern-matching function, and returns a decorator that adds the patterns in the existing function to the new function being decorated, where the new patterns are checked first, then the existing. Equivalent to:

def prepattern(base_func):
    """Decorator to add a new case to
       a pattern-matching function, 
       where the new case is checked first."""
    def pattern_prepender(func):
        def pre_pattern_func(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except MatchError:
                return base_func(*args, **kwargs)
        return pre_pattern_func
    return pattern_prepender

c49

con Python –come già detto.

reduce
Coconut re-introduces Python 2’s reduce built-in, using the functools.reduce version.
Apply function of two arguments cumulatively to the items of sequence, from left to right, so as to reduce the sequence to a single value. For example, reduce((x, y) -> x+y, [1, 2, 3, 4, 5]) calculates ((((1+2)+3)+4)+5). The left argument, x, is the accumulated value and the right argument, y, is the update value from the sequence. If the optional initializer is present, it is placed before the items of the sequence in the calculation, and serves as a default when the sequence is empty. If initializer is not given and sequence contains only one item, the first item is returned.

c50

takewhile
Coconut provides itertools.takewhile as a built-in under the name takewhile.
takewhile(predicate, iterable)
Make an iterator that returns elements from the iterable as long as the predicate is true. Equivalent to:

def takewhile(predicate, iterable):
    # takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4
    for x in iterable:
        if predicate(x):
            yield x
        else:
            break

L’esempio proposto mi da errore, forse dovuto alla versione 😦

Coconut:
negatives = takewhile(numiter, (x) -> x<0)

Python:
import itertools
negatives = itertools.takewhile(numiter, lambda x: x<0)


dropwhile
Coconut provides itertools.dropwhile as a built-in under the name dropwhile.

dropwhile(predicate, iterable)
Make an iterator that drops elements from the iterable as long as the predicate is true; afterwards, returns every element. Note: the iterator does not produce any output until the predicate first becomes false, so it may have a lengthy start-up time. Equivalent to:

def dropwhile(predicate, iterable):
    # dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1
    iterable = iter(iterable)
    for x in iterable:
        if not predicate(x):
            yield x
            break
    for x in iterable:
        yield x

Come per il caso precedente ottengo un errore.

Coconut:
positives = dropwhile(numiter, (x) -> x<0)

Python:
import itertools
positives = itertools.dropwhile(numiter, lambda x: x<0)

tee
Coconut provides itertools.tee as a built-in under the name tee.
tee(iterable, n=2)
Return n independent iterators from a single iterable. Equivalent to:

def tee(iterable, n=2):
    it = iter(iterable)
    deques = [collections.deque() for i in range(n)]
    def gen(mydeque):
        while True:
            if not mydeque:             # when the local deque is empty
                newval = next(it)       # fetch a new value and
                for d in deques:        # load it to all the deques
                    d.append(newval)
            yield mydeque.popleft()
    return tuple(gen(d) for d in deques)

Once tee() has made a split, the original iterable should not be used anywhere else; otherwise, the iterable could get advanced without the tee objects being informed.

This itertool may require significant auxiliary storage (depending on how much temporary data needs to be stored). In general, if one iterator uses most or all of the data before another iterator starts, it is faster to use list() instead of tee().

c51

consume
Coconut provides the consume function to efficiently exhaust an iterator and thus perform any lazy evaluation contained within it. consume takes one optional argument, keep_last, that defaults to 0 and specifies how many, if any, items from the end to return as an iterable (None will keep all elements). Equivalent to:

def consume(iterable, keep_last=0):
    """Fully exhaust iterable and return the last keep_last elements."""
    return collections.deque(iterable, maxlen=keep_last) 
                                    # fastest way to exhaust an iterator

In the process of lazily applying operations to iterators, eventually a point is reached where evaluation of the iterator is necessary. To do this efficiently, Coconut provides the consume function, which will fully exhaust the iterator given to it.

c52

count
Coconut provides a modified version of itertools.count that supports in, normal slicing, optimized iterator slicing, count and index sequence methods, repr, and _start and _step attributes as a built-in under the name count.
count(start=0, step=1)
Make an iterator that returns evenly spaced values starting with number start. Often used as an argument to map() to generate consecutive data points. Also, used with zip() to add sequence numbers. Roughly equivalent to:

def count(start=0, step=1):
    # count(10) --> 10 11 12 13 14 ...
    # count(2.5, 0.5) -> 2.5 3.0 3.5 ...
    n = start
    while True:
        yield n
        n += step

c53

Verifica:

c53-1

In Python can’t be done quickly without Coconut’s iterator slicing, which requires many complicated pieces. The necessary definitions in Python can be found in the Coconut header.

map and zip
Coconut’s map and zip objects are enhanced versions of their Python equivalents that support normal slicing, optimized iterator slicing (through __coconut_is_lazy__), reversed, len, repr, and have added attributes which subclasses can make use of to get at the original arguments to the object (map supports _func and _iters attributes and zip supports the _iters attribute).

c54

In Python can’t be done without defining a custom map type.

datamaker
Coconut provides the datamaker function to allow direct access to the base constructor of data types created with the Coconut data statement. This is particularly useful when writing alternative constructors for data types by overwriting __new__. Equivalent to:

def datamaker(data_type):
    """Returns base data constructor of data_type."""
    return super(data_type, data_type).__new__$(data_type)

Coconut:

data trilen(h):
def __new__(cls, a, b):
return (a**2 + b**2)**0.5 |> datamaker(cls)

Python:

import collections
class trilen(collections.namedtuple("trilen", "h")):
    __slots__ = ()
    def __new__(cls, a, b):
        return super(cls, cls).__new__(cls, (a**2 + b**2)**0.5)


recursive

Coconut provides a recursive decorator to perform tail recursion optimization on a function written in a tail-recursive style, where it directly returns all calls to itself. Do not use this decorator on a function not written in a tail-recursive style or the function will likely break.

c55

La REPL visualizza male la riga “raise TypeError("the argument must be an integer >= 0")“.

In Python can’t be done without a long decorator definition. The full definition of the decorator in Python can be found in the Coconut header.

parallel_map
Coconut provides a parallel version of map under the name parallel_map. parallel_map makes use of multiple processes, and is therefore often much faster than map. Use of parallel_map requires concurrent.futures, which exits in the Python 3 standard library, but under Python 2 will require python -m pip install futures to function.
Because parallel_map uses multiple processes for its execution, it is necessary that all of its arguments be pickleable. Only objects defined at the module level, and not lambdas, objects defined inside of a function, or objects defined inside of the interpreter, are pickleable. Furthermore, on Windows, it is necessary that all calls to parallel_map occur inside of an if __name__ == "__main__" guard.

parallel_map(_func, *iterables_)

Equivalent to map(func, *iterables) except func is executed asynchronously and several calls to func may be made concurrently. If a call raises an exception, then that exception will be raised when its value is retrieved from the iterator.

c56

e

c57

MatchError
A MatchError is raised when a destructuring assignment statement fails, and thus MatchError is provided as a built-in for catching those errors. MatchError objects support two attributes, pattern, which is a string describing the failed pattern, and value, which is the object that failed to match that pattern.

:mrgreen:

Coconut – Istruzioni – 11

no-fun-allowed

Non so se si userà Coconut ma rockz 😀 continuo da qui a copiare qui.

Istruzioni

Coconut supports significantly enhanced destructuring assignment, similar to Python’s tuple/list destructuring, but much more powerful. The syntax for Coconut’s destructuring assignment is

[match] <pattern> = <value> 

where <value> is any expression and <pattern> is defined by Coconut’s match statement. The match keyword at the beginning is optional, but is sometimes necessary to disambiguate destructuring assignment from normal assignment, which will always take precedence. Coconut’s destructuring assignment is equivalent to a match statement that follows the syntax:

match <pattern> in <value>:
    pass
else:
    err = MatchError(<error message>)
    err.pattern = "<pattern>"
    err.value = <value>
    raise err

If a destructuring assignment statement fails, then instead of continuing on as if a match block had failed, a MatchError object will be raised describing the failure.

c46

With Python can’t be done without a long series of checks in place of the destructuring assignment statement. See the compiled code for the Python syntax.

Decoratori
Unlike Python, which only supports a single variable or function call in a decorator, Coconut supports any expression.

L’esempio riportato non è completo e non ho trovato qualcosa di diverso da uno che seguirà prossimamente. Per cui riporto solo il codice senza eseguirlo.

Coconut:

@wrapper1 .. wrapper2 $(arg)
def func(x) = x**2

Python:

def wrapper(func):
    return wrapper1(wrapper2(arg, func))
@wrapper
def func(x):
    return x**2

Istruzioni else
Coconut supports the compound statements try, if, and match on the end of an else statement like any simple statement would be. This is most useful for mixing match and if statements together, but also allows for compound try statements.

Coconut:

try:
    unsafe_1()
except MyError:
    handle_1()
else: try:
    unsafe_2()
except MyError:
    handle_2()

Python:

try:
    unsafe_1()
except MyError:
    handle_1()
else:
    try:
        unsafe_2()
    except MyError:
        handle_2()

Istruzioni except
Python 3 requires that if multiple exceptions are to be caught, they must be placed inside of parentheses, so as to disallow Python 2’s use of a comma instead of as. Coconut allows commas in except statements to translate to catching multiple exceptions without the need for parentheses.

Coconut:

try:
    unsafe_func(arg)
except SyntaxError, ValueError as err:
    handle(err)

Python:

try:
    unsafe_func(arg)
except (SyntaxError, ValueError) as err:
    handle(err)


Lista di variabili

Coconut allows for the more elegant parenthetical continuation instead of the less elegant backslash continuation in import, del, global, and nonlocal statements.

c47

Codice passthrough
No, non so tradurlo (codice attraversante? orrendo!).
Coconut supports the ability to pass arbitrary code through the compiler without being touched, for compatibility with other variants of Python, such as Cython or Mython. Anything placed between \( and the corresponding close parenthesis will be passed through, as well as any line starting with \\, which will have the additional effect of allowing indentation under it.

Coconut:

\\cdef f(x):
    return x |> g

Python:

cdef f(x):
    return g(x)

:mrgreen: