23. Đối tượng mã

Đối tượng mã là bản trình bày được biên dịch của CPython về mã Python thực thi.

Nó chứa mã byte và siêu dữ liệu. Trình thông dịch có thể thực thi nó, nhưng bản thân đối tượng mã không mang trạng thái thời gian chạy như toàn cục, đối số mặc định, ô đóng hoặc phương thức bị ràng buộc.

Đối với nguồn này:python def add(a, b): return a + b đối tượng chức năngaddchứa một đối tượng mã:```python code = add.code

print(code.co_name) print(code.co_varnames) print(code.co_consts) print(code.co_names)


## 23.1 Vị trí trong Đường dẫn biên dịch

Các đối tượng mã là đầu ra ca quá trình biên dch.```text
source text
    
tokenization
    
parsing
    
AST
    
symbol table
    
compiler
    
code object
    
frame execution
```Đối tượng mã là s chuyn giao gia trình biên dch và trình thông dch.

Trình biên dch phát ra các đối tượng mã.

Vòng đánh giá thc thi các đối tượng mã bên trong các khung.

## 23.2 Đối tượng mã và Đối tượng hàm

Mt đối tượng hàm bao bc mt đối tượng mã.

Ví d:```python
def f(x):
    return x + 1
```Khi chy:```text
function object
    __code__       code object
    __globals__    module globals dictionary
    __defaults__   positional defaults
    __kwdefaults__ keyword-only defaults
    __closure__    closure cells
    __dict__       function attributes
    __name__       function name
    __qualname__   qualified name
```Đối tượng mã cha ni dung được biên dch.```text
code object
    bytecode
    constants
    names
    local variable names
    free variable names
    cell variable names
    filename
    line information
    stack size
    flags
```V mt lý thuyết, cùng mt đối tượng mã có th được s dng bi nhiu đối tượng hàm.```python
import types

def f(x):
    return x + 1

g = types.FunctionType(f.__code__, globals(), "g")

print(g(10))
```Mã được chia s. Trình bao bc hàm thay đổi liên kết thi gian chy.

## 23.3 Đối tượng mã là bất biến

Các đối tượng mã là bt biến.

Sau khi được to, mã byte, hng s, tên biến, c và siêu d liu ca đối tượng mã không th thay đổi ti ch.

Điu này quan trng đối vi thiết kế an toàn và thi gian chy. Nhiu hàm hoc khung có th tham chiếu đến cùng mt đối tượng mã. Nếu các đối tượng mã có th thay đổi được thì vic thay đổi mt đối tượng có th nh hưởng đến mã hin đang chy.

Để sa đổi mã, các công c to mt đối tượng mã mi.

Python hin đại bc l mt`replace()`phương pháp:```python
def f():
    return 1

new_code = f.__code__.replace(co_name="renamed")
```Điu này to ra mt bn sao được sa đổi thay vì chnh sa đối tượng ban đầu.

## 23.4 Đối tượng mã mô-đun

Mt mô-đun cũng có mt đối tượng mã.

Ví d:```python
src = """
x = 1
y = 2
print(x + y)
"""

code = compile(src, "example.py", "exec")
```Đối tượng mã này đại din cho vic thc thi cp cao nht.

Nó không có tham s chc năng. Không gian tên cc b ca nó thường là t đin mô-đun.

Thanh tra:```python
print(code.co_name)
print(code.co_filename)
print(code.co_consts)
print(code.co_names)
print(code.co_varnames)
```Đối vi mã mô-đun,`co_name`thường xuyên`"<module>"`.

Trình thông dch thc thi đối tượng mã này vi toàn cc và cc b. Nhp thông thường, thc thi tp lnh và`exec()`tt c đều s dng các đối tượng mã kiu mô-đun.

## 23.5 Đối tượng mã biểu thức`compile()`cũng có thể tạo ra các đối tượng mã biểu thức.

Ví d:```python
code = compile("1 + 2", "<input>", "eval")
result = eval(code)

print(result)
```MT`eval`đối tượng mã đại din cho mt biu thc. Nó tr v giá tr biu thc.

Điu này khác vi`exec`cách thc:```python
compile("x = 1", "<input>", "exec")
compile("1 + 2", "<input>", "eval")

execchế độ chấp nhận các câu lệnh.evalchế độ chỉ chấp nhận một biểu thức.

Chế độ này thay đổi cả điểm bắt đầu ngữ pháp và hành vi của đối tượng mã được tạo.

23.6 Đối tượng mã tương tác

Sử dụng chế độ tương tác"single"biên soạn.

Ví dụ:```python code = compile("1 + 2", "", "single") exec(code)


Đây là lý do ti sao REPL hot động khác vi vic thc thi tp lnh.```text
exec mode:
    execute statements normally

eval mode:
    return expression value

single mode:
    behave like interactive input
```Đối tượng mã ghi li đủ thông tin để trình thông dch chy chính xác chế độ đã chn.

## 23.7 Đối tượng mã lồng nhau

Các cu trúc thc thi lng nhau to ra các đối tượng mã lng nhau.

Ví d:```python
def outer(x):
    def inner(y):
        return x + y
    return inner
```Đối tượng mã mô-đun cha đối tượng mã cho`outer`TRONG`co_consts`.

các`outer`đối tượng mã cha đối tượng mã cho`inner`riêng ca nó`co_consts`.

Thanh tra:```python
def outer(x):
    def inner(y):
        return x + y
    return inner

outer_code = outer.__code__
print(outer_code.co_consts)

for const in outer_code.co_consts:
    if isinstance(const, type(outer_code)):
        print("nested code:", const.co_name)
```Các đối tượng mã lng nhau là các hng s vì chúng là d liu được biên dch được nhúng trong đối tượng mã kèm theo.

Vào thi gian chy,`MAKE_FUNCTION`to các đối tượng hàm t các đối tượng mã đó.

## 23,8`co_code`

`co_code`lưu tr byte mã byte.

Ví d:```python
def f(a, b):
    return a + b

print(f.__code__.co_code)
```thô`co_code`đọc trc tiếp không d chu chút nào. S dng`dis`:

```python
import dis

dis.dis(f)
```Bytecode là lung lnh cho máy o CPython.

Mi lnh có mt opcode và có th có mt đối s. Mã hóa chính xác thay đổi gia các phiên bn, vì vy các công c nên s dng`dis`thay vì bù đắp byte mã hóa cng.

## 23,9`co_consts`

`co_consts`lưu tr các hng s được tham chiếu bi mã byte.

Ví d:```python
def f():
    return 1, "x", None
```Thanh tra:```python
print(f.__code__.co_consts)
```Ni dung đin hình:```text
(None, 1, 'x')
```Các hng s có th bao gm:```text
None
booleans
numbers
strings
bytes
tuples of constants
frozensets
nested code objects
```Trình biên dch loi b trùng lp mt s hng s trong mt đối tượng mã.

Hướng dn mã byte ti hng s theo ch mc:```text
LOAD_CONST 1
```có nghĩa là ti`co_consts[1]`.

## 23.10`co_names`

`co_names`lưu tr tên được s dng để tra cu toàn cu, tra cu thuc tính, nhp và các hot động tương t.

Ví d:```python
def f(xs):
    return len(xs)
```Thanh tra:```python
print(f.__code__.co_names)
```Có kh năng đầu ra:```text
('len',)
```Mã byte s dng mt ch mc vào`co_names`:

```text
LOAD_GLOBAL 0
```có nghĩa là ti tên chung hoc tên dng sn`co_names[0]`.

Ví d vi quyn truy cp thuc tính:```python
def f(obj):
    return obj.value

valuexuất hiện ởco_namesvì tên thuộc tính cũng được lưu trữ ở đó.

23.11co_varnames

co_varnameslưu trữ tên biến cục bộ.

Ví dụ:python def f(a, b): c = a + b return c Thanh tra:python print(f.__code__.co_varnames) Đầu ra điển hình:text ('a', 'b', 'c') Mã byte cục bộ nhanh sử dụng các chỉ mục trong bộ dữ liệu này.```text LOAD_FAST 0 a LOAD_FAST 1 b STORE_FAST 2 c


## 23.12`co_freevars`Và`co_cellvars`Việc đóng cửa sử dụng hai trường đối tượng mã.

| Lĩnh vc | Ý nghĩa |
| ------------- | ---------------------------------------- |
|`co_cellvars`| Người dân địa phương b bt bi phm vi lng nhau |
|`co_freevars`| Các biến được ghi li t phm vi kèm theo |

Ví d:```python
def outer():
    x = 1

    def inner():
        return x

    return inner
```Thanh tra:```python
print(outer.__code__.co_cellvars)

inner = outer()
print(inner.__code__.co_freevars)
```Hình dng d kiến:```text
('x',)
('x',)
```Vì`outer`, `x`là mt biến ô vì mã lng nhau cn nó.

Vì`inner`, `x`là mt biến min phí vì nó xut phát t mt phm vi kèm theo.

## 23.13 Ô đóng cửa không được lưu trữ trong đối tượng mã

Mt đối tượng mã ghi li nhng biến rnh ri mà nó cn. Nó không lưu tr các giá tr thc tế được ghi li.

Các giá tr được ghi li nm trong các ô đóng được gn vào đối tượng hàm.

Ví d:```python
def make_reader(value):
    def read():
        return value
    return read

f = make_reader(42)

print(f.__code__.co_freevars)
print(f.__closure__)
print(f.__closure__[0].cell_contents)
```Đối tượng mã nói:```text
this function needs a free variable named value
```Đối tượng chc năng cung cp:```text
the actual cell containing 42
```S tách bit này cho phép tái s dng cùng mt đối tượng mã lng nhau vi các giá tr được ghi li khác nhau.

## 23.14`co_argcount`và siêu dữ liệu đối số

Đối tượng mã lưu tr s lượng đối s.

Các trường quan trng bao gm:```text
co_argcount
co_posonlyargcount
co_kwonlyargcount
co_varnames
co_flags
```Ví d:```python
def f(a, b, /, c, *, d):
    return a, b, c, d
```Thanh tra:```python
code = f.__code__

print(code.co_argcount)
print(code.co_posonlyargcount)
print(code.co_kwonlyargcount)
print(code.co_varnames)
```Các trường này giúp máy gi hàm liên kết các đối s vi các v trí biến cc b.

Giá tr mc định không được lưu tr trong đối tượng mã. Chúng sng trên đối tượng hàm:```python
def f(x=1):
    return x

print(f.__defaults__)
print(f.__code__.co_consts)
```Giá tr mc định thuc v đối tượng hàm vì giá tr mc định được đánh giá ti thi đim định nghĩa hàm.

## 23,15`co_flags`

`co_flags`lưu tr các c thc thi.

C mô t các thuc tính như:```text
has *args
has **kwargs
is generator
is coroutine
is async generator
uses nested scopes
future flags
```Ví d:```python
def normal():
    return 1

def gen():
    yield 1

async def coro():
    return 1
```Thanh tra:```python
print(normal.__code__.co_flags)
print(gen.__code__.co_flags)
print(coro.__code__.co_flags)
```B thc thi s dng các c này để quyết định đối tượng nào s được to khi hàm được gi.

Hàm to tr v mt đối tượng trình to.

Hàm coroutine tr v mt đối tượng coroutine.

Mt hàm bình thường s thc thi bình thường và tr v mt giá tr.

## 23.16`co_stacksize`

`co_stacksize`ghi li độ sâu ngăn xếp đánh giá ti đa mà đối tượng mã cn.

Ví d:```python
def f(a, b, c):
    return a + b * c
```Trình biên dch tính toán mc s dng ngăn xếp t các hiu ng ngăn xếp mã byte.

V mt khái nim:```text
LOAD_FAST a       stack depth 1
LOAD_FAST b       stack depth 2
LOAD_FAST c       stack depth 3
BINARY_OP *       stack depth 2
BINARY_OP +       stack depth 1
RETURN_VALUE      stack depth 0
```Độ sâu ti đa: 3.

Khung s dng`co_stacksize`để phân b đủ dung lượng lưu tr ngăn xếp.

## 23.17 Siêu dữ liệu nguồn

Đối tượng mã lưu tr siêu d liu ngun.

Các trường quan trng bao gm:```text
co_filename
co_name
co_qualname
co_firstlineno
line table data
position table data
```Ví d:```python
def f():
    x = 1
    return x

code = f.__code__

print(code.co_filename)
print(code.co_name)
print(code.co_qualname)
print(code.co_firstlineno)
```Siêu d liu này h tr:```text
tracebacks
debuggers
profilers
coverage tools
inspection
warnings
error locations
```Nếu không có siêu d liu ngun, vic thc thi Python vn có th thc hin được nhưng vic chn đoán s t hơn nhiu.

## 23.18 Bảng và vị trí đường

Các đối tượng mã ánh x độ lch mã byte tr li v trí ngun.

Bn có th kim tra các v trí:```python
def f(x):
    return x + 1

for item in f.__code__.co_positions():
    print(item)
```Ánh x ngun này h tr truy nguyên và g li chính xác.

Các phiên bn CPython cũ hơn s dng các định dng bng s dòng khác nhau. Các phiên bn hin đại hin th thông tin v trí phong phú hơn, bao gm c độ lch ct.

Các công c nên ưu tiên các phương thc công khai hơn là phân tích cú pháp trc tiếp các bng nh phân riêng tư.

## 23.19 Bảng ngoại lệ

Các đối tượng mã CPython hin đại bao gm thông tin bng ngoi l.

Các bng ngoi l mô t phm vi mã byte nào được bo v bi trình x lý ngoi l.

Ví d:```python
def f():
    try:
        risky()
    except ValueError:
        recover()
```Bn thân mã byte không đủ. Trình thông dch cũng cn siêu d liu như:```text
protected instruction range
handler target
stack depth restoration information
handler kind
```Siêu d liu này cho phép CPython trin khai`try`, `except`, `finally`và lung điu khin liên quan.

## 23.20 Tạo đối tượng mã từ`compile()`các`compile()`tích hợp tạo ra các đối tượng mã.

Ví d:```python
code = compile("x = 1\n", "<input>", "exec")

ns = {}
exec(code, ns)

print(ns["x"])
```Đối vi biu thc:```python
code = compile("1 + 2", "<input>", "eval")

print(eval(code))
```Đối vi đầu vào AST:```python
import ast

tree = ast.parse("x = 1\n")
code = compile(tree, "<ast>", "exec")

compile()chạy cùng một đường dẫn rộng được sử dụng cho các tệp:```text source or AST ↓ validation ↓ symbol analysis ↓ bytecode generation ↓ code object


Các đối tượng mã có thể được thực thi với`exec()`hoặc`eval()`.

Ví dụ:```python
code = compile("x = 10\n", "<input>", "exec")

globals_dict = {}
locals_dict = {}

exec(code, globals_dict, locals_dict)

print(locals_dict["x"])

exec()cung cấp không gian tên thời gian chạy.

Bản thân đối tượng mã không chứa các không gian tên đó.

Đối với mã biểu thức:```python code = compile("x + 1", "", "eval")

print(eval(code, {"x": 41}))


## 23.22 Đối tượng và khung mã

Khung là mt phiên bn đang chy ca mt đối tượng mã.

Đối tượng mã:```text
immutable compiled instructions
```Khung:```text
current execution state
instruction pointer
local variables
evaluation stack
block state
globals
builtins
exception state
```Ví d:```python
def f(x):
    y = x + 1
    return y
```Mi cuc gi đến`f`to hoc s dng khung thc thi`f.__code__`.

Nhiu cuc gi s dng cùng mt đối tượng mã nhưng trng thái khung khác nhau.```text
f.__code__
    shared by all calls

frame for f(1)
    x = 1
    y = 2

frame for f(10)
    x = 10
    y = 11
```## 23.23 Đối tượng mã và`marshal`CPython có thể tuần tự hóa các đối tượng mã bằng`marshal`.

biên son`.pyc`các tp cha các đối tượng mã được sp xếp theo th t cng vi siêu d liu tiêu đề.

Đây là cách thc hin c th. các`marshal`định dng không phi là định dng tun t hóa có mc đích chung n định.

Quy tc thc tế:```text
use pickle or another format for application data
use marshal only for CPython internals or closely related tooling
```Khi Python nhp mt mô-đun, CPython có th ti mt mô-đun được lưu vào b nh đệm`.pyc`tp, đọc đối tượng mã và thc thi nó thay vì biên dch li ngun.

## 23.24 Đối tượng mã trong`.pyc`Tập tin

A`.pyc`tp tin lưu tr d liu b đệm bytecode đã biên dch.

V mt khái nim:```text
.pyc file
    header
        magic number
        invalidation metadata
    marshalled module code object
```Đối tượng mã mô-đun có th cha các đối tượng mã ni dung lp và hàm lng nhau trong`co_consts`.

B đệm mã byte tăng tc độ khi động bng cách tránh phân tích cú pháp và biên dch lp đi lp li khi ngun không thay đổi.

Nhưng`.pyc`các tp tin có phiên bn c th. Các định dng bytecode và marshal có th thay đổi trên các phiên bn CPython.

## 23.25 Ranh giới bảo mật đối tượng mã

Đối tượng mã là d liu thc thi.

Chy mt đối tượng mã tương đương vi vic chy mã.

Ví d:```python
code = compile("import os; os.remove('file.txt')", "<input>", "exec")
exec(code)
```Đối tượng mã không tr nên an toàn vì nó đã được biên dch.

Các h thng nhy cm v bo mt không được thc thi các đối tượng mã không đáng tin cy, ngun không đáng tin cy hoc mã byte được sp xếp theo th t không đáng tin cy.

Quá trình biên dch không phi là sandboxing.

## 23.26 Xem xét nội tâm đối tượng mã

Các đối tượng mã rt hu ích cho vic xem xét ni tâm.

Ví d:```python
def f(a, b=1):
    c = a + b
    return c

code = f.__code__

for name in [
    "co_argcount",
    "co_posonlyargcount",
    "co_kwonlyargcount",
    "co_nlocals",
    "co_stacksize",
    "co_flags",
    "co_consts",
    "co_names",
    "co_varnames",
    "co_freevars",
    "co_cellvars",
]:
    print(name, getattr(code, name))
```Điu này h tr các công c như:```text
debuggers
profilers
coverage tools
tracers
decorators
test frameworks
bytecode inspectors
static analysis helpers
```## 23.27 Thay thế đối tượng mã

Các đối tượng mã có th được sao chép vi các sa đổi bng cách s dng`replace()`.

Ví d:```python
def f():
    return 1

new_code = f.__code__.replace(co_name="g")
```Điu này rt hu ích cho các công c nâng cao.

Nhưng vic thay đổi ni b đối tượng mã có th d dàng vi phm các gi định. Ví d: mã byte, hng s, tên, kích thước ngăn xếp, c và bng ngoi l phi nht quán.

Đối tượng mã b hng có th làm hng công c, gây ra li khó hiu hoc hot động không đúng.

S dng`replace()`để chnh sa siêu d liu hoc công vic mã byte được xác thc cn thn.

## 23.28 Đối tượng mã được dành riêng cho từng phiên bản

Các trường đối tượng mã và chi tiết mã byte thay đổi trên các phiên bn Python.

Ví d v các khu vc nhy cm vi phiên bn:```text
opcode names
opcode arguments
inline cache layout
exception table format
line table format
code object constructor signature
optimization behavior
```Các công c mnh m nên s dng API công khai:```text
dis
inspect
types.CodeType.replace
co_positions()
co_lines()
ast
compile
```Tránh gi định rng b cc mã byte thô vn n định.

## 23,29 Vùng nguồn CPython

Các tp ngun CPython quan trng bao gm:```text
Include/cpython/code.h
Objects/codeobject.c
Python/compile.c
Python/assemble.c
Python/flowgraph.c
Python/marshal.c
Lib/dis.py
Lib/inspect.py
Lib/types.py
```Vai trò khái nim:

| Khu vc | Vai trò |
| -------------- | ---------------------------------- |
|`code.h`| Định nghĩa cu trúc đối tượng mã |
|`codeobject.c`| To và hành vi đối tượng mã |
|`compile.c`| AST để to lnh |
|`assemble.c`| Tp hp đối tượng mã cui cùng |
|`flowgraph.c`| X lý biu đồ lung điu khin |
|`marshal.c`| Tun t hóa cho b đệm mã byte |
|`dis.py`| Kim tra mã byte có th đọc được ca con người |

## 23.30 Mô hình tinh thần tối thiểu

S dng mô hình này:```text
A code object is immutable compiled Python code.
It contains bytecode plus metadata.
A function object wraps a code object with runtime context.
A frame executes a code object.
Nested functions, lambdas, classes, comprehensions, and generators have nested code objects.
Constants, names, locals, free variables, and cell variables are stored in code object tables.
The interpreter uses the code object to allocate frames and run bytecode.
```Đối tượng mã là to phm được biên dch để kết ni trình biên dch ca CPython vi máy o ca nó.