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 odpowiedzi
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
.
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).
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ść
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 :)
Podobne pytania
Nowe pytania
python
Python to wielozadaniowy, wielozadaniowy język programowania dynamicznie typowany. Został zaprojektowany tak, aby był szybki do nauczenia się, zrozumienia i użycia oraz wymuszania czystej i jednolitej składni. Należy pamiętać, że Python 2 oficjalnie nie jest obsługiwany od 01-01-2020. Mimo to, w przypadku pytań Pythona specyficznych dla wersji, dodaj znacznik [python-2.7] lub [python-3.x]. Korzystając z wariantu Pythona (np. Jython, PyPy) lub biblioteki (np. Pandas i NumPy), należy umieścić go w tagach.