Używam modułu "dis", aby ponownie napisać skompilowany skrypt (.pyc). Rozumiem różnicę między JUMP_FORWARD i JUMP_ABSOLUTE. Według mojej wiedzy instrukcji IF będzie zamknięty przez JUMP_FORWARD:JUMP_FORWARD lub JUMP_ABSOLUTE z instrukcją IF? Python 2.5
>>> def f():
if a:
print ''
>>> from dis import dis
>>> dis(f)
2 0 LOAD_GLOBAL 0 (a)
3 JUMP_IF_FALSE 9 (to 15)
6 POP_TOP
3 7 LOAD_CONST 1 ('')
10 PRINT_ITEM
11 PRINT_NEWLINE
12 JUMP_FORWARD 1 (to 16)
>> 15 POP_TOP
>> 16 LOAD_CONST 0 (None)
19 RETURN_VALUE
A JUMP_ABSOLUTE pojawi się, jeśli oświadczenie IF jest na końcu innej pętli. Na przykład:
>>> def f1():
if a:
if b:
print ''
>>> dis(f1)
2 0 LOAD_GLOBAL 0 (a)
3 JUMP_IF_FALSE 20 (to 26)
6 POP_TOP
3 7 LOAD_GLOBAL 1 (b)
10 JUMP_IF_FALSE 9 (to 22)
13 POP_TOP
4 14 LOAD_CONST 1 ('')
17 PRINT_ITEM
18 PRINT_NEWLINE
19 JUMP_ABSOLUTE 27
>> 22 POP_TOP
23 JUMP_FORWARD 1 (to 27)
>> 26 POP_TOP
>> 27 LOAD_CONST 0 (None)
30 RETURN_VALUE
Z Bytecode czytam odpisać kod, istnieje JUMP_ABSOLUTE która mnie zaskakuje:
121 228 LOAD_FAST 11 (a)
231 LOAD_CONST 9 (100)
234 COMPARE_OP 0 (<)
237 JUMP_IF_FALSE 23 (to 263)
240 POP_TOP
241 LOAD_FAST 11 (b)
244 LOAD_CONST 11 (10)
247 COMPARE_OP 4 (>)
250 JUMP_IF_FALSE 10 (to 263)
253 POP_TOP
122 254 LOAD_CONST 3 (1)
257 STORE_FAST 4 (ok)
260 JUMP_ABSOLUTE 27
>> 263 POP_TOP
Myślę kod jest następujący:
if a<100 and b>10:
ok=1
ale powoduje to JUMP_FORWARD, a nie JUMP_ABSOLUTE. Wiem, że nie jest to pętla WHILE, ani instrukcja FOR, ponieważ oba tworzą linię SETUP_LOOP w kodzie Bajt.
Moje pytanie brzmi: czego mi brakuje? dlaczego dostaję DO PRZODU zamiast skoku ABSOLUTE?
EDIT: absolutny skok do indeksu 27 punktów na początku (gdy?) Pętli, w którym te dwie linie 121 i 122 należą do:
106 24 SETUP_LOOP 297 (to 324)
>> 27 LOAD_FAST 4 (ok)
30 LOAD_CONST 1 (0)
33 COMPARE_OP 2 (==)
36 JUMP_IF_FALSE 283 (to 322)
39 POP_TOP
Jest IF-oświadczenie przed i innym jeden po tych liniach. Oto kod wcześniej, z tym samym JUMP_ABSOLUTE zamykającym instrukcję.
115 170 LOAD_FAST 3 (q)
173 LOAD_CONST 10 (1)
176 COMPARE_OP 0 (<)
179 JUMP_IF_FALSE 45 (to 227)
182 POP_TOP
183 LOAD_FAST 11 (z)
186 LOAD_CONST 11 (10)
189 COMPARE_OP 4 (>)
192 JUMP_IF_FALSE 32 (to 227)
195 POP_TOP
116 196 LOAD_CONST 1 (0)
199 STORE_FAST 4 (ok)
117 202 LOAD_FAST 5 (u)
205 LOAD_CONST 3 (1)
208 BINARY_ADD
209 STORE_FAST 5 (u)
118 212 LOAD_CONST 1 (0)
215 STORE_FAST 3 (k)
119 218 LOAD_CONST 3 (10)
221 STORE_FAST 6 (dv)
224 JUMP_ABSOLUTE 27
>> 227 POP_TOP
JUMP_FORWARD mówi „przejść do następnej linii” i JUMP_ABSOLUTE mówi „wróć do początku pętli while”. Problem polega na tym, że nie wiem, jak skopiować kod, który dałby ten sam kod bajtowy, jak powyżej.
Dziękujemy!
był twój ' .pyc' stworzone z tą samą wersją Pythona, jakiego używasz teraz? Która to jest wersja? –
Jestem całkiem pewien, że został utworzony za pomocą Pythona 2.5, tego samego używam właśnie teraz.Sprawdziłem magiczną liczbę. – Alex
Wspomniałeś, że wiesz, że to nie jest pętla. Ale JUMP_ABSOLUTE 27 wskazuje, że skok zabiera cię z powrotem daleko w kodzie. Czy wyglądałeś tak daleko jak opcode z indeksem 27, aby zobaczyć, do czego faktycznie wskakiwał, aby upewnić się, że to nie jest pętla? Korzystne może być dodanie większej ilości zdemontowanego kodu, aby uzyskać pełny obraz, zwłaszcza, że można zobaczyć, do czego przeskakuje. –