Piszę trzy linie tego samego kodu i uzyskać inny wynik, po pierwsze uruchomię go w jednej interaktywnej skorupce:

>>> a = 10000
>>> b = 10000
>>> a is b
False

>>> a = 10000; b = 10000; a is b
True

Wtedy mam jeden plik Pythona, który zawiera:

a = 10000
b = 10000
print a is b

Uruchamiam to i zdobyć True

Moje środowisko Pythona:

Python 2.7.5 (default, Mar  9 2014, 22:15:05) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

Co tu się dzieje? Wszyscy mówią o kompilacji, czy ktoś wie, jak kompilacja interaktywnej skorupy i prowadzi te linie kodu?

4
fengsp 13 sierpień 2014, 12:49

4 odpowiedzi

Najlepsza odpowiedź

Jeśli umieścisz w funkcji, zostanie również oceniona True. To, co się dzieje, jest to, że Python wykonuje listę stałch stosowanych przy kompilacji funkcji do BYTECODE, a równe stałe będą "zawalone" w jednej wartości, która jest ładowana dwa razy. Wygląda na to, że interaktywny tłumacz ma to samo przy kompilacji jednej linii kodu *

Oto ByteCode dla jednej z tych funkcji uzyskanych przy użyciu dis - W rzeczywistości jest to samo dla każdej metody z wyjątkiem dla numerów linii, więc nie kopiuję ich tutaj.

  2           0 LOAD_CONST               1 (10000)
              3 STORE_FAST               0 (a)
              6 LOAD_CONST               1 (10000)
              9 STORE_FAST               1 (b)
             12 LOAD_FAST                0 (a)
             15 LOAD_FAST                1 (b)
             18 COMPARE_OP               8 (is)
             21 RETURN_VALUE

To jest dla:

def func():
    a = 10000; b = 10000; return a is b
from dis import dis
dis(func)

Należy pamiętać, że obie linie LOAD_CONST mają ten sam argument. Jest to odniesienie do indeksu w func.__code__.co_consts, która jest krotka. Element 1 tego krotki jest obiekt int 10000.

Tylko dla całości "Sake", oto demontaż oryginalnej a = 10000; b = 10000; a is b Jeśli compile() to:

  1           0 LOAD_CONST               0 (10000)
              3 STORE_NAME               0 (a)
              6 LOAD_CONST               0 (10000)
              9 STORE_NAME               1 (b)
             12 LOAD_NAME                0 (a)
             15 LOAD_NAME                1 (b)
             18 COMPARE_OP               8 (is)
             21 POP_TOP
             22 LOAD_CONST               1 (None)
             25 RETURN_VALUE

Jest to fundamentalnie podobny, z wyjątkiem numeru linii / numer Const, NAME vs FAST i zakończenie z POP_TOP. Podczas gdy przydzielisz wartości na oddzielnych liniach, nie robi tego ze stałymi, więc tworzy nowy obiekt INT za każdym razem.

* Aby dodać nieco więcej intrygi, jeśli umieściłem wersję jednorazową do mojego notebooka IPython, a is b False.

3
Jason S 13 sierpień 2014, 09:34

Myślę, że to optymalizacja czasu kompilacji. W pierwszym przypadku kompilujesz a = 10000, a następnie b = 10000, więc kompilator bajtów nie ma (prosty) sposób określania ich tożsamości.

W innych przypadkach kompilator widzi, że a i b są zainicjowane przy użyciu tego samego dosłownego i nie zostaną zmienione później.

Nie ma to nic wspólnego z małą optymalizacją całkowitą. Ten również pracuje na wyrażenia, tj.

>> a = 256; b = 256; a is b
True

Ale

>> a = 256; b = 256; a + 1 is b + 1
False

Odpowiedni kod jest częścią Optymalizacji Pythona Peephole (patrz https://Python/python/blob/master/python/peepole.c).

1
filmor 13 sierpień 2014, 10:54

Chociaż świeży Pythona, spróbuj to wyjaśnić. Oświadczenie "jest" dowiedzieć się, że treść rzeczy jest taka sama lub nie. W twoim przykładzie, jeśli "jest" używany, Python sprawdzi "A" i "B" wskazując to samo, czy nie. Jeśli zmienisz swój program: A = 1 B = 1 A oznacza B Udrukowanie True może być odnoszą się do metody Pythona, jak przechowywać wartość

0
BinDu 13 sierpień 2014, 08:59

Właśnie to zrozumiałem, właściwie to 10000, które mają ten sam identyfikator, znajdują się w kompilacyjnym obiekcie kodu ::

>>> code = compile("a = 10000; b = 10000; a is b", "<string>", "exec")
>>> code.co_consts
(10000, None)

Kompilator wykonuje pewną optymalizację, a 10000 jest właśnie tworzone raz, ponieważ 10000 jest niezmienny :)

0
fengsp 13 sierpień 2014, 09:13