Re: [Python] Annidamento di funzioni

2013-03-22 Per discussione Marco Giusti
On Thu, Mar 21, 2013 at 09:31:11PM +, Daniele Varrazzo wrote:
 On 2013-03-21 19:16, Matteo Boscolo wrote:
 
 * quante volte posso annidare una funzione dentro un altra prima che
 python si incazzi ?
 
 Nell'ordine della dimensione dello stack direi, per cui tu ti
 scoccierai molto prima di quando l'interprete perderà la pazienza.
 
 * c'è qualche problema di performance nell'annidare le funzioni in
 questo modo ?
 
 No: in realtà le funzioni vengono compilate quando il modulo è
 importato, insieme a quelle esterne, e non quando la funzione
 interna viene chiamata: la loro compilazione è statica. Quello che
 fa il def è solo creare una chiusura, ovvero associare l'oggetto
 di codice al valore delle variabili non-locali. Un po' di curiosità
 nell'interprete interattivo aiuta a capire:

molto interessante.

 La programmazione a oggetti è un modo inferiore di fare la stessa
 cosa: associare uno stato a del codice. La sto buttando un po'
 trollosa
[...]

credo di aver capito cosa intendi ma mi sembra un po' riduttivo ridurre
la programmazione ad oggetti a questo.
___
Python mailing list
Python@lists.python.it
http://lists.python.it/mailman/listinfo/python


[Python] Annidamento di funzioni

2013-03-21 Per discussione Matteo Boscolo

Ciao a tutti,

vorrei sfruttare la possibilità di annidare le funzioni di python in 
questo modo:


def solve():
a1=100
a2=1
def nodeA():
a=a1
b=20
def nodeB():
c=a+b
return {'a':a,'c':c}
return {'a':a,'b':b,'nodneB':nodeB()}
def nodeC():
a=a2
b=20
def nodeB():
a=1999
c=a+b
return {'a':a,'c':c}
return {'a':a,'b':b,'nodneB':nodeB()}

return nodeA(),nodeC()

print A,solve()

e' solo un codice di studio, quindi il ritorno delle varie funzioni non 
e' particolarmente importante per ora.
in pratica il mio codice dovrebbe creare questa sruttura a runtime e 
compilarla e prendere il valore di solve() Questo lo so gia fare ...

tutto questo per sfruttare gli scope di python ..

a questo punto vi chiedo?

* quante volte posso annidare una funzione dentro un altra prima che 
python si incazzi ?
* c'è qualche problema di performance nell'annidare le funzioni in 
questo modo ?
* c'è un modo alternativo di implementare sta roba ottenendo il 
comportamento dello scope di python.


qualsiasi idea e benvenuta..

ciao
Matteo





___
Python mailing list
Python@lists.python.it
http://lists.python.it/mailman/listinfo/python


Re: [Python] Annidamento di funzioni

2013-03-21 Per discussione Daniele Varrazzo

On 2013-03-21 19:16, Matteo Boscolo wrote:


* quante volte posso annidare una funzione dentro un altra prima che
python si incazzi ?


Nell'ordine della dimensione dello stack direi, per cui tu ti 
scoccierai molto prima di quando l'interprete perderà la pazienza.



* c'è qualche problema di performance nell'annidare le funzioni in
questo modo ?


No: in realtà le funzioni vengono compilate quando il modulo è 
importato, insieme a quelle esterne, e non quando la funzione interna 
viene chiamata: la loro compilazione è statica. Quello che fa il def è 
solo creare una chiusura, ovvero associare l'oggetto di codice al 
valore delle variabili non-locali. Un po' di curiosità nell'interprete 
interattivo aiuta a capire:



In [2]: def f(x):
a = 10
def g(y):
return x + y + a
return g
   ...:

In [13]: f.func_code.co_consts
Out[13]:
(None,
 10,
 code object g at 0xb6b3ef98, file 
ipython-input-2-880615467131, line 3)


L'oggetto di codice g è una costante della funzione f, già compilata.


In [3]: f3 = f(3)

In [18]: f3(1)
Out[18]: 14

In [4]: f3.func_closure
Out[4]:
(cell at 0x983ad64: int object at 0x953d098,
 cell at 0x983af5c: int object at 0x953d044)

In [9]: f3.func_closure[0].cell_contents
Out[9]: 3

In [10]: f3.func_closure[1].cell_contents
Out[10]: 10

La funzione f è stata decorata con una chiusura, che contiene i 
valori delle variabili non locali



In [20]: import dis

In [22]: dis.dis(f3)
  4   0 LOAD_DEREF   0 (x)
  3 LOAD_FAST0 (y)
  6 BINARY_ADD
  7 LOAD_DEREF   1 (a)
 10 BINARY_ADD
 11 RETURN_VALUE

Le variabili della chiusura vengono lette con un opcode che ha solo un 
argomento posizionale: accedervi è veloce quanto accedere alle variabili 
locali (ovvero più veloce che alle variabili globali, che richiedono un 
lookup di dizionario)



In [14]: g5 = f(5)

In [17]: g5.func_code is f.func_code.co_consts[2]
Out[17]: True

Il codice della funzione restituita è proprio quello della funzione 
compilata.


Ed ecco il lavoro che fa la funzione esterna: non compila niente, crea 
solo la chiusura:


In [3]: dis.dis(f)
  2   0 LOAD_CONST   1 (10)
  3 STORE_DEREF  0 (a)

  3   6 LOAD_CLOSURE 1 (x)
  9 LOAD_CLOSURE 0 (a)
 12 BUILD_TUPLE  2
 15 LOAD_CONST   2 (code object g at 
0xb6ab1848, file ipython-input-1-880615467131, line 3)

 18 MAKE_CLOSURE 0
 21 STORE_FAST   1 (g)

  5  24 LOAD_FAST1 (g)
 27 RETURN_VALUE



* c'è un modo alternativo di implementare sta roba ottenendo il
comportamento dello scope di python.


Usare classi e oggetti, facendoti le chiusure da te.

La programmazione a oggetti è un modo inferiore di fare la stessa cosa: 
associare uno stato a del codice. La sto buttando un po' trollosa, ma è 
così: i linguaggi funzionali non hanno mai sentito la mancanza degli 
oggetti. È stato il C, che non avendo un garbage collector, ha avuto 
bisogno di mettere puntatori a funzioni dentro una struttura, creando 
l'implementazione degli oggetti che è stata formalizzata col C++. Java 
invece, avendo un GC, non aveva nessun motivo per non introdurre le 
chiusure dal giorno zero; invece hanno preferito perdere 20 anni dietro 
un design che era alla moda quel mercoledì. Chi pensa che il lisp sia 
inferiore perché non ha le classi non c'ha capito niente, e come al 
solito chi non conosce il lisp è destinato a reinventarlo (vedi Java 7).



--
Daniele Varrazzo - Develer S.r.l.
http://www.develer.com
___
Python mailing list
Python@lists.python.it
http://lists.python.it/mailman/listinfo/python