2015-12-12 10 views
9

In Python, le espressioni come 10**9 fatte di letterali sono anche letterali? Quello che sto chiedendo: c'è un costo per usare le espressioni su letterali meno significativi ma anche meno calcolabili nel codice che viene chiamato molto spesso e dovrebbe essere leggero?Il costo dell'utilizzo di 10 ** 9 su 1000000000?

risposta

6

Si tratta di leggibilità e stile di codifica. Scrivendo qualcosa come 10**9 invece di 1000000000 o ecc., Il codice verrà ridotto e più leggibile, pertanto la manutenzione e il miglioramento saranno più semplici. Se si desidera utilizzare 10**9 più volte nel codice, in un modo più elegante è preferibile utilizzarlo come variabile globale al livello più alto del modulo che è più elegante. Come:

MY_VARIABLE = 10**9 

Nota che anche se non si utilizza un nome di variabile globale e utilizzare il suo valore numerico tramite il codice Python assumerà si tratta di un valore costante e non sarà ricalcolare ogni volta.

Ad esempio, come si può vedere nella seguente bytecode, pitone caricherà il valore costante (che definita in prima parte di a) per c e non crea un nuovo oggetto per questo:

>>> def test(): 
... a = 10**9 
... b = 1000000000 
... c = 10**9 
... 
>>> dis.dis(test) 
    2   0 LOAD_CONST    4 (1000000000) 
       3 STORE_FAST    0 (a) 

    3   6 LOAD_CONST    3 (1000000000) 
       9 STORE_FAST    1 (b) 

    4   12 LOAD_CONST    5 (1000000000) 
      15 STORE_FAST    2 (c) 
      18 LOAD_CONST    0 (None) 
      21 RETURN_VALUE  

Nota che Python piccoli interi sono single e pitone creerà una sola copia di loro (da -5 a 256).

+4

Non è più leggibile perché è più breve. È più leggibile perché non devi contare zero. –

+1

@Rhymoid In effetti, ed era quello che intendevo. – Kasramvd

+0

nit: il tuo b è 10 ** 8 – wim

13

Non ci sono costi di prestazioni. Considerate questo:

import dis 
def foo(): 
    x = 10**9 
    y = 10**9 

def bar(): 
    x = 1000000000 
    y = 1000000000 

dis.dis(foo) 
dis.dis(bar) 

cede

In [6]: dis.dis(foo) 
    5   0 LOAD_CONST    3 (1000000000) 
       3 STORE_FAST    0 (x) 

    6   6 LOAD_CONST    4 (1000000000) 
       9 STORE_FAST    1 (y) 
      12 LOAD_CONST    0 (None) 
      15 RETURN_VALUE   

In [8]: dis.dis(bar) 
    9   0 LOAD_CONST    1 (1000000000) 
       3 STORE_FAST    0 (x) 

10   6 LOAD_CONST    1 (1000000000) 
       9 STORE_FAST    1 (y) 
      12 LOAD_CONST    0 (None) 
      15 RETURN_VALUE   

Così, quando Python compila il codice, cambia il 10**9-1000000000. Nel momento in cui viene eseguito il codice byte, non vi è alcuna differenza tra l'utilizzo di 10**9 o 1000000000.

+0

Penso che questo "piegamento costante" sia comunque un dettaglio di implementazione cpython. – wim

1

Dopo sé riflessione, ho fatto alcune misure di tempo:

>>> import timeit 

>>> def f(): 
...  return 10**9 

>>> timeit.timeit(f) 
0.13885498046875 

>>> def f(): 
...  return 1000000000 

>>> timeit.timeit(f) 
0.13900208473205566 
1

Ci è un costo per usare le espressioni, vale a dire un costo delle prestazioni a causa di Python precomputing constant expressions, ma questo costo non è probabile che sia evidente nella maggior parte dei casi, come nel caso di 10**9, più ancora con casi come 10**(10**10).

+0

Buona referenza! Quindi quello che stai dicendo è che il calcolo è stato aggiunto, ma una volta in fase di compilazione? – ArekBulski