Dịch ngược mã máy Python: function/lambda

by Pymier0

Tiếp loạt bài về CPython compiler img

Code định nghĩa 2 function dùng def và lambda:

# $ cat -n fun.py
     1  def sum_two(x, y):
     2      z = x + y
     3      return z
     4
     5  a = 5
     6  b = 7
     7  sum_two(a, b)
     8
     9  double = lambda x: x * 2
    10  double(5)

Chạy dis. Việc tạo function dùng def hay lambda đều sử dụng BYTECODE MAKE_FUNCTION sau đó STORE_NAME

  1           0 LOAD_CONST               0 (<code object sum_two at 0x7fc64dcca190, file "fun.py", line 1>)
              2 LOAD_CONST               1 ('sum_two')
              4 MAKE_FUNCTION            0
              6 STORE_NAME               0 (sum_two)

  5           8 LOAD_CONST               2 (5)
             10 STORE_NAME               1 (a)

  6          12 LOAD_CONST               3 (7)
             14 STORE_NAME               2 (b)

  7          16 LOAD_NAME                0 (sum_two)
             18 LOAD_NAME                1 (a)
             20 LOAD_NAME                2 (b)
             22 CALL_FUNCTION            2
             24 POP_TOP

  9          26 LOAD_CONST               4 (<code object <lambda> at 0x7fc64dcca2f0, file "fun.py", line 9>)
             28 LOAD_CONST               5 ('<lambda>')
             30 MAKE_FUNCTION            0
             32 STORE_NAME               3 (double)

 10          34 LOAD_NAME                3 (double)
             36 LOAD_CONST               2 (5)
             38 CALL_FUNCTION            1
             40 POP_TOP
             42 LOAD_CONST               6 (None)
             44 RETURN_VALUE

Disassembly of <code object sum_two at 0x7fc64dcca190, file "fun.py", line 1>:
  2           0 LOAD_FAST                0 (x)
              2 LOAD_FAST                1 (y)
              4 BINARY_ADD
              6 STORE_FAST               2 (z)

  3           8 LOAD_FAST                2 (z)
             10 RETURN_VALUE

Disassembly of <code object <lambda> at 0x7fc64dcca2f0, file "fun.py", line 9>:
  9           0 LOAD_FAST                0 (x)
              2 LOAD_CONST               1 (2)
              4 BINARY_MULTIPLY
              6 RETURN_VALUE

khác với các khái niệm trước, khi viết function sẽ thấy python dis riêng ra từng mục cho từng function.

Với function sum_two tại dòng 1, có riêng mục

Disassembly of <code object sum_two at 0x7fc64dcca190, file "fun.py", line 1>:

chú ý thêm sự khác biệt khi dùng biến trong function sử dụng LOAD_FAST thay vì LOAD_NAME, tạo biến sử dụng STORE_FAST thay STORE_NAME. function kết thúc bằng việc RETURN_VALUE.

Thế nhưng.. return cái gì? câu RETURN_VALUE không thấy ghi thêm gì sau, làm sao biết nó return gì? RETURN_VALUE sẽ return giá trị cuối cùng tính toán được. Như trong sum_two sẽ return giá trị của z sau khi LOAD_FAST. Với lambda function, return kết quả của phép nhân BINARY_MULTIPLY. Cụ thể hơn, trong Python VM gọi đây là TOP OF STACK (TOS), kết quả của giá trị tính toán xong sẽ luôn nằm ở đây. Vậy nếu muốn return giá trị không phải là tính cuối cùng thì sao?

Thử nghiệm với 2 function không trả về giá trị vừa tính xong:

     1  def r_none(x, y):
     2      z = x + y
     3      return
     4
     5
     6  def r_i(x, y):
     7      i = 8
     8      z = x + y
     9      return i

Kết quả dis

Disassembly of <code object r_none at 0x7fdd4b47bdf0, file "fun.py", line 1>:
  2           0 LOAD_FAST                0 (x)
              2 LOAD_FAST                1 (y)
              4 BINARY_ADD
              6 STORE_FAST               2 (z)

  3           8 LOAD_CONST               0 (None)
             10 RETURN_VALUE

Disassembly of <code object r_i at 0x7fdd4b47f030, file "fun.py", line 6>:
  7           0 LOAD_CONST               1 (8)
              2 STORE_FAST               2 (i)

  8           4 LOAD_FAST                0 (x)
              6 LOAD_FAST                1 (y)
              8 BINARY_ADD
             10 STORE_FAST               3 (z)

  9          12 LOAD_FAST                2 (i)
             14 RETURN_VALUE

function r_none load giá trị None để return vì code chỉ ghi return không gì cả. function r_i sẽ LOAD_FAST giá trị i rồi return i.

Đăng ký ngay tại PyMI.vn để học Python tại Hà Nội TP HCM (Sài Gòn), trở thành lập trình viên #python chuyên nghiệp ngay sau khóa học.