Tôi đã sử dụng mô-đun 'dis' để viết lại một số tập lệnh được biên dịch (.pyc). Tôi hiểu sự khác biệt giữa JUMP_FORWARD và JUMP_ABSOLUTE. Theo hiểu biết của tôi một IF tuyên bố sẽ đóng cửa bởi một JUMP_FORWARD:JUMP_FORWARD hoặc JUMP_ABSOLUTE với câu lệnh 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
Và JUMP_ABSOLUTE sẽ xuất hiện nếu IF tuyên bố là ở phần cuối của vòng lặp khác. Ví dụ:
>>> 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
Từ Bytecode Tôi đọc để viết lại mã, có một JUMP_ABSOLUTE rằng tôi ngạc nhiên:
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
Tôi nghĩ rằng các mã như sau:
if a<100 and b>10:
ok=1
nhưng nó kích hoạt JUMP_FORWARD chứ không phải JUMP_ABSOLUTE. Tôi biết nó không phải là một vòng lặp WHILE, cũng như một câu lệnh FOR vì cả hai đều tạo ra một dòng SETUP_LOOP trong Bytecode.
Câu hỏi của tôi là: tôi đang thiếu gì? tại sao tôi nhận được FORWARD thay vì nhảy ABSOLUTE?
EDIT: Các bước nhảy tuyệt đối để chỉ số 27 điểm để khởi đầu của một (KHI?) Vòng lặp trong đó hai dòng 121 và 122 thuộc về:
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
Có một IF-tuyên bố trước và khác một sau những dòng này. Đây là mã trước, với cùng một JUMP_ABSOLUTE đóng câu lệnh.
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 nói "đi tới dòng tiếp theo" và JUMP_ABSOLUTE nói "quay lại phần đầu của vòng WHILE". Vấn đề là tôi không biết làm thế nào để tái tạo một mã mà sẽ cung cấp cho cùng một bytecode như trên.
Cảm ơn bạn!
Là bạn ' .pyc' được tạo bằng cùng phiên bản Python như bạn đang sử dụng? Phiên bản nào vậy? –
Tôi khá chắc chắn nó đã được tạo bằng Python 2.5, giống như tôi đang sử dụng ngay bây giờ.Tôi đã kiểm tra số ma thuật. – Alex
Bạn đã đề cập rằng bạn biết đây không phải là vòng lặp. Nhưng JUMP_ABSOLUTE 27 chỉ ra rằng bước nhảy đang đưa bạn trở lại khá lâu trong đoạn mã. Bạn đã nhìn xa như opcode với chỉ mục 27 để xem nó thực sự nhảy trở lại, để đảm bảo đây không phải là một vòng lặp? Nó có thể mang lại lợi ích khi bao gồm thêm mã tháo rời để cung cấp cho bức tranh hoàn chỉnh, đặc biệt là để có thể nhìn thấy nơi nhảy tới. –