2015-12-12 28 views
9

W języku Python są wyrażenia takie jak 10**9 wykonane z literałów również literałów? O co pytam: Czy koszt używania wyrażeń jest mniej znaczący, ale także mniej obliczalne literały w kodzie, który jest nazywany bardzo często i powinien być lekki?Koszt korzystania z 10 ** 9 ponad 1000000000?

Odpowiedz

6

Chodzi bardziej o czytelność i styl kodowania. Pisząc coś takiego jak 10**9 zamiast 1000000000 itp., Sprawisz, że twój kod będzie krótszy i bardziej czytelny, a więc jego konserwacja i doskonalenie będzie łatwiejsze. Jeśli chcesz wielokrotnie używać kodu 10**9 w swoim kodzie, jako bardziej elegancki sposób lepiej użyj go jako zmiennej globalnej na najwyższym poziomie modułu, który jest bardziej elegancki. Jak:

MY_VARIABLE = 10**9 

Uwaga, że nawet jeśli nie korzystają z globalną nazwę zmiennej i użyć jej wartość liczbową za pośrednictwem kodu Pythona będzie zakładać, że jest to wartość stała i nie będzie przeliczyć to za każdym razem.

Na przykład, jak widać na poniższym kodu bajtowego Python załaduje wartość stałą (co zdefiniowano w pierwszej części za a) dla c i nie tworzy nowy obiekt za to:

>>> 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  

Uwaga że Python małych liczb całkowitych są singletons i python stworzy tylko jedną kopię nich (-5 do 256).

+4

Nie jest bardziej czytelny, ponieważ jest krótszy. Jest bardziej czytelny, ponieważ nie trzeba liczyć zer. –

+1

@Rhymoid Rzeczywiście, i to miałem na myśli. – Kasramvd

+0

nit: twój b to 10 ** 8 – wim

13

Nie ma żadnych kosztów wydajności. Rozważ to:

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

def bar(): 
    x = 1000000000 
    y = 1000000000 

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

daje

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   

Więc kiedy Python kompiluje kod, zmienia 10**9 do 1000000000. Do czasu uruchomienia kodu bajtowego nie ma różnicy między używaniem 10**9 lub 1000000000.

+0

Myślę, że to "stałe składanie" jest jednak szczegółem implementacji cpython. – wim

1

Po autorefleksji, zrobiłem kilka pomiarów czasowych:

>>> import timeit 

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

>>> timeit.timeit(f) 
0.13885498046875 

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

>>> timeit.timeit(f) 
0.13900208473205566 
1

Nie jest koszt do używania wyrażeń, a mianowicie koszt wydajność ze względu na Python precomputing constant expressions, ale koszt ten nie jest prawdopodobne, aby być zauważalne w większości przypadków, jak w przypadku 10**9, w przypadku takich przypadków jak 10**(10**10).

+0

Dobry odnośnik! Więc to, co mówisz, to to, że dodawana jest obliczalność, ale jednorazowa kompilacja? – ArekBulski