6. Từ mã nguồn đến thực thi

CPython không thực thi trực tiếp văn bản nguồn Python. Nó biến đổi văn bản nguồn thông qua một số biểu diễn bên trong trước khi lệnh mã byte đầu tiên chạy.

Con đường là:```text source text ↓ tokens ↓ parse tree ↓ abstract syntax tree ↓ symbol table ↓ code object ↓ frame ↓ bytecode evaluation ↓ object operations


## 6.1 Văn bản nguồn

Đầu vào bt đầu dưới dng văn bn.```python
x = 1 + 2
print(x)
```Trước khi CPython có th thc hin điu này, nó phi biết:```text
where statements begin and end
which characters form names
which characters form numbers
which indentation levels define blocks
which tokens form expressions
which names are local or global
which bytecode instructions are needed
```Mã ngun Python không ch là mt chui. Nó có mã hóa, cu trúc dòng, tht l, nhn xét, quy tc chui ký t và quy tc cú pháp.

Giai đon đầu tiên chuyn đổi văn bn thô thành mã thông báo.

## 6.2 Mã thông báo

Trình mã thông báo đọc các ký t ngun và to mã thông báo.

Đối vi mã này:```python
x = 1 + 2
```trình mã thông báo to ra mt lung tương t như:```text
NAME("x")
EQUAL("=")
NUMBER("1")
PLUS("+")
NUMBER("2")
NEWLINE
ENDMARKER
```Đối vi cu trúc khi, tht l cũng tr thành mã thông báo.```python
if ok:
    run()
else:
    stop()
```V mt khái nim:```text
NAME("if")
NAME("ok")
COLON
NEWLINE
INDENT
NAME("run")
LPAR
RPAR
NEWLINE
DEDENT
NAME("else")
COLON
NEWLINE
INDENT
NAME("stop")
LPAR
RPAR
NEWLINE
DEDENT
ENDMARKER
```Điu này rt quan trng. Cu trúc khi Python không được suy ra sau này t khong trng. Trình mã thông báo phát ra rõ ràng`INDENT`Và`DEDENT`mã thông báo.

## 6.3 Phân tích cú pháp

Trình phân tích cú pháp s dng mã thông báo và kim tra xem chúng có to thành cú pháp Python hp l hay không.

Vì:```python
x = 1 + 2
```trình phân tích cú pháp nhn ra câu lnh gán có phía bên phi là biu thc nh phân.

Vì:```python
def add(a, b):
    return a + b
```trình phân tích cú pháp nhn ra:```text
function definition
function name
parameter list
function body
return statement
binary expression
```Trình phân tích cú pháp t chi các chui mã thông báo không hp l:```python
x = + * 3
```Điu này đến được trình phân tích cú pháp, nhưng nó không th rút gn thành cú pháp hp l.

Đầu ra ca trình phân tích cú pháp là mt biu din có cu trúc ca chương trình. CPython sau đó chuyn đổi cu trúc đó thành AST.

## 6.4 Cây cú pháp trừu tượng

AST đại din cho cu trúc ng nghĩa ca chương trình.

Vì:```python
x = 1 + 2
```AST v mt khái nim là:```text
Module
    Assign
        target: Name("x", Store)
        value:
            BinOp
                left: Constant(1)
                op: Add
                right: Constant(2)
```AST loi b nhiu chi tiết b mt và gi li cu trúc cn thiết cho các giai đon biên dch sau này.

Bn có th kim tra AST t Python:```python
import ast

tree = ast.parse("x = 1 + 2")
print(ast.dump(tree, indent=4))
```Hình dng đầu ra ví d:```text
Module(
    body=[
        Assign(
            targets=[
                Name(id='x', ctx=Store())],
            value=BinOp(
                left=Constant(value=1),
                op=Add(),
                right=Constant(value=2)))],
    type_ignores=[])
```AST cho biết ý nghĩa ca chương trình v mt cu trúc. Nó vn chưa cho biết hướng dn mã byte nào s phát ra.

## 6.5 Bối cảnh tên

Tên AST mang theo ng cnh.

Trong mã này:```python
x = x + 1
```hai công dng ca`x`có nhng vai trò khác nhau.```text
left side x     Store
right side x    Load
```V mt khái nim:```text
Assign
    target: Name("x", Store)
    value:
        BinOp
            left: Name("x", Load)
            op: Add
            right: Constant(1)
```S khác bit này quan trng vì vic ti tên và lưu tr tên s biên dch thành các hot động khác nhau.```text
Load context     read a value
Store context    assign a value
Del context      delete a binding
```Trình biên dch da vào thông tin này khi phát ra mã byte.

## 6.6 Phân tích bảng ký hiệu

Trước khi to mã byte, CPython phân tích tên.

Nó quyết định xem mi tên có phi là:```text
local
global
nonlocal
free
cell
implicit builtin lookup
```Ví d:```python
x = 10

def f(y):
    return x + y
```Bên trong`f`:

```text
y is local
x is global or builtin lookup
```Mt ví d khác:```python
def outer():
    x = 10

    def inner():
        return x

    return inner
```Đây:```text
x is local in outer
x is free in inner
x becomes a cell variable in outer
```Biến ô là biến cc b phi tn ti vì hàm bên trong nm bt nó. Biến t do là biến được hàm s dng nhưng được lưu tr trong phm vi kèm theo.

Giai đon này là cn thiết cho vic đóng ca.

## 6.7 Đối tượng mã

Sau khi phân tích cú pháp và ký hiu, CPython biên dch mã thành các đối tượng mã.

Mt đối tượng mã cha:```text
bytecode
constants
names
local variable names
free variable names
cell variable names
stack size
flags
filename
function name
line mapping information
exception table
```Bn có th kim tra mt đối tượng mã:```python
def add(a, b):
    return a + b

code = add.__code__

print(code.co_name)
print(code.co_varnames)
print(code.co_consts)
print(code.co_names)
print(code.co_freevars)
print(code.co_cellvars)
```Đối tượng mã là bt biến. Nó mô t mã thc thi nhưng không cha các giá tr thi gian chy hin ti ca các biến cc b.

## 6,8 Mã byte

Bytecode là định dng hướng dn ca CPython.

Vì:```python
def add(a, b):
    return a + b
```vic tháo g có th trông ging như:```text
LOAD_FAST a
LOAD_FAST b
BINARY_OP +
RETURN_VALUE
```Tên và b cc mã byte thc tế khác nhau tùy theo phiên bn Python. Ý tưởng ct lõi vn là: hướng dn mã byte hot động trên mt khung.

S dng`dis`:

```python
import dis

def add(a, b):
    return a + b

dis.dis(add)
```Mã byte  cp độ thp hơn AST. Nó gn đến vic thc hin.

AST nói:```text
return a + b
```Mã byte nói:```text
load a
load b
perform addition
return result
```## 6.9 Hằng số và tên

Đối tượng mã lưu tr các hng s và tên riêng bit vi mã byte.

Vì:```python
x = 10
print(x)
```hng s`10`được lưu tr trong bng hng s. Nhng cái tên`x`Và`print`được lưu tr trong bng tên.

V mt khái nim:```text
co_consts = (10, None)
co_names  = ("x", "print")
```Mã byte sau đó s tham chiếu các bng này theo ch mc.```text
LOAD_CONST 0       load constant 10
STORE_NAME 0       store into name x
LOAD_NAME 1        load name print
LOAD_NAME 0        load name x
CALL 1
POP_TOP
LOAD_CONST 1       load None
RETURN_VALUE
```Điu này làm cho mã byte tr nên nh gn. Hướng dn lưu tr các ch mc nh thay vì chui hoc đối tượng đầy đủ.

## 6.10 Thực thi mô-đun

Mt tp Python được biên dch thành mt đối tượng mã cp mô-đun.

Vì:```python
# demo.py
x = 1

def f():
    return x
```CPython biên dch toàn b tp thành mt đối tượng mã. Vic thc thi đối tượng mã đó s to ra các ràng buc mô-đun.

V mt khái nim:```text
create module object
create module dictionary
execute module code object in that dictionary
bind x
create function object f
bind f
```Phn thân hàm cũng được biên dch thành đối tượng mã riêng ca nó. Đối tượng mã mô-đun cha đối tượng mã chc năng đó dưới dng hng s.

Điu này gii thích ti sao vic xác định hàm s thc thi mã ti thi đim nhp mô-đun: phn thân không chy nhưng đối tượng hàm được to và liên kết.

## 6.11 Định nghĩa hàm

Mt định nghĩa hàm là mã thc thi được.

Vì:```python
def add(a, b):
    return a + b
```CPython không chy phn thân ngay lp tc. Nó to ra mt đối tượng chc năng.

V mt khái nim:```text
load code object for add
load function name
create function object
store function object in current namespace
```Đối tượng hàm cha:```text
code object
globals dictionary
default values
closure cells
annotations
metadata
```Sau đó, khi hàm được gi, CPython s to mt khung t đối tượng hàm đó và thc thi đối tượng mã ca hàm.

## 6.12 Tạo khung

Mt khung được to khi CPython thc thi mt đối tượng mã.

Đối vi mt cuc gi chc năng:```python
add(2, 3)
```CPython to khung vi:```text
code object for add
globals from add.__globals__
builtins
local slots
argument values
value stack
instruction pointer
exception state
```Các đối s được đặt vào các v trí biến cc b.```text
a = 2
b = 3
```Sau đó, trình đánh giá mã byte bt đầu thc thi khung.

## 6.13 Ngăn xếp đánh giá

Hu hết các hướng dn mã byte đều giao tiếp thông qua ngăn xếp giá tr ca khung.

Vì:```python
return a + b
```vic thc hin là:```text
LOAD_FAST a      push value of a
LOAD_FAST b      push value of b
BINARY_OP +      pop two values, add, push result
RETURN_VALUE     pop result and return it
```Các biến cc b được lưu tr riêng bit vi các giá tr ngăn xếp tm thi.```text
locals:
    a = 2
    b = 3

stack:
    temporary values used by bytecode
```Đây là lý do ti sao CPython được gi là máy o da trên ngăn xếp.

## 6.14 Thao tác đối tượng

Các hướng dn mã byte hot động trên các đối tượng Python, không phi các nguyên hàm C thô.

Khi CPython thc thi:```python
a + b
```nó không cho rng`a`Và`b`là s nguyên ca máy.

H có th là:```text
integers
floats
strings
lists
tuples
NumPy arrays
user-defined objects
```Hot động gi đi thông qua giao thc đối tượng.

Vì`int + int`, CPython s dng phép cng s nguyên. Vì`str + str`, nó s dng ni chui. Đối vi các lp do người dùng định nghĩa, nó có th gi`__add__`.

V mt khái nim:```text
BINARY_OP +
    inspect operand types
    find numeric operation
    call appropriate slot
    return Python object
```Đây là lý do ti sao mã byte vn chung chung trong khi các loi cung cp hành vi c th.

## 6.15 Truy cập thuộc tính

Dành cho:```python
obj.name
```CPython biên dch ti thuc tính.

V mt khái nim:```text
LOAD_FAST obj
LOAD_ATTR name
```Vào thi gian chy,`LOAD_ATTR`thc hin các quy tc tra cu thuc tính Python:```text
check type descriptors
check instance dictionary
check non-data descriptors and class attributes
possibly call __getattr__
raise AttributeError if missing
```Truy cp thuc tính không phi là tra cu trường thô trong trường hp chung. Đó là mt hot động giao thc.

Điu này gii thích ti sao quyn truy cp thuc tính có th chy mã Python.```python
class C:
    @property
    def name(self):
        print("computed")
        return 42

obj = C()
obj.name
```Thuc tính đọc mã mô t cuc gi.

## 6.16 Cuộc gọi

Dành cho:```python
result = f(2, 3)
```CPython đánh giá đối s và đối s có th gi được, sau đó thc hin cuc gi.

V mt khái nim:```text
load f
load 2
load 3
call with 2 positional arguments
store result
```Trong thi gian chy, có th gi được:```text
Python function
built-in C function
bound method
class object
object with __call__
partial object
method descriptor
```Lnh gi hàm Python s to mt khung mi. Lnh gi tích hp C gi trình bao bc hàm C. Mt cuc gi lp phân b và khi to mt th hin.

Hướng dn mã byte là chung chung. Công văn thi gian chy quyết định đường dn cuc gi chính xác.

## 6.17 Luồng điều khiển

Lung điu khin được biên dch thành các bước nhy.

Vì:```python
if x:
    a()
else:
    b()
```CPython phát ra mã byte có hình dng như:```text
load x
jump if false to else
call a
jump to end
else:
call b
end:
```Đối vi các vòng lp biên dch thành các hot động ca giao thc iterator cng vi các bước nhy.```python
for x in items:
    use(x)
```V mt khái nim:```text
get iterator
loop_start:
    get next item
    if exhausted, jump to loop_end
    store x
    call use(x)
    jump to loop_start
loop_end:
```Tính năng ngôn ng  mc cao. Mô hình thc thi là nhy mã byte và gi giao thc.

## 6.18 Xử lý ngoại lệ

X lý ngoi l biên dch thành phm vi mã byte được bo v và siêu d liu trình x lý.

Vì:```python
try:
    risky()
except ValueError:
    recover()
```CPython cn biết:```text
which bytecode range is protected
where the handler starts
which exception type to match
how to unwind the stack
where execution continues
```Khi mt ngoi l xy ra, người đánh giá s tham kho siêu d liu x lý ngoi l và chuyn quyn kim soát sang trình x lý thích hp nếu phù hp.

Nếu không có trình x lý nào khp vi khung hin ti, ngoi l s truyn ti người gi.

## 6.19 Nhập khẩu

Câu lnh nhp là mã thc thi.```python
import math
```Trong thi gian chy, CPython s dng máy nhp để:```text
check sys.modules
find a module spec
load or create the module
execute module code if needed
bind the name
```H thng nhp được trin khai mt phn bng Python thông qua`importlib`và được h tr mt phn bi mã thi gian chy C.

Mt tp mô-đun được biên dch và thc thi ging như các mã Python khác, nhưng không gian tên thc thi ca nó là t đin mô-đun.

## 6.20 Hiểu biết

Mt s hiu biết có phm vi thc hin riêng ca nó.

Vì:```python
squares = [x * x for x in range(10)]
```CPython to mã cho phn ni dung hiu.

V mt khái nim:```text
call range(10)
get iterator
create result list
run comprehension code
append each computed value
store final list in squares
```Biến vòng lp`x`thuc phm vi bên trong ca s hiu biết, không phi phm vi chc năng xung quanh.

Đây là lý do ti sao:```python
[x for x in range(3)]
print(x)
```không ràng buc`x`trong phm vi xung quanh trong Python hin đại.

## 6.21 Đóng cửa

Đóng ca yêu cu các tế bào.

Vì:```python
def outer():
    x = 10

    def inner():
        return x

    return inner

innersử dụng một biến từouter.

CPython không thể lưu trữxnhư một địa phương nhanh bình thường sẽ biến mất khioutertrở lại. Nó lưu trữxtrong một đối tượng ô.

Về mặt khái niệm:text outer local x becomes cell variable inner references x as free variable inner function stores reference to the cell cell keeps x alive after outer returns Đây là lý do tại sao hàm trả về vẫn hoạt động:```python f = outer() print(f())


## 6.22 Máy phát điện

Hàm to s biên dch khác vi hàm thông thường.```python
def count():
    yield 1
    yield 2
```Đang gi`count()`to ra mt đối tượng máy phát đin. Nó không ngay lp tc chy cơ th.

Đối tượng trình to lưu tr trng thái thc thi b treo:```text
code object
frame or frame-like execution state
instruction offset
local variables
value stack state
running status
```Mi`next()`tiếp tc thc hin cho đến ln tiếp theo`yield`.

```python
g = count()
next(g)
next(g)
```MT`yield`không ch là s tr li. Nó tm dng khung và duy trì trng thái thc thi.

## 6.23 Coroutine

Mt coroutine tương t như mt máy phát đin, nhưng nó tham gia vào quá trình`await`giao thc.```python
async def fetch():
    value = await operation()
    return value
```Đang gi`fetch()`to ra mt đối tượng coroutine. Phn thân ch chy khi coroutine được ch đợi hoc lên lch.

Coroutine lưu tr trng thái thc thi b đình ch và tiếp tc li trong khong thi gian đó`await`đim.

V mt khái nim:```text
create coroutine object
start execution
reach await
suspend coroutine
resume later with result
continue execution
return final value
```Vòng lp s kin nm ngoài mô hình mã byte ct lõi, nhưng vic tm dng và tiếp tc coroutine là các tính năng thi gian chy được trin khai bi các đối tượng và khung CPython.

## 6.24 Định nghĩa lớp

Mt câu lnh lp là mã thc thi được.```python
class C:
    x = 1

    def f(self):
        return self.x
```CPython không ch phân b mt kiu tĩnh. Nó thc thi phn thân lp trong mt không gian tên tm thi.

V mt khái nim:```text
load class name
prepare class namespace
execute class body code object
collect attributes and methods
call metaclass
bind resulting class object to name C
```Điu này gii thích ti sao thân lp có th cha mã tùy ý:```python
class C:
    print("building class")
    x = 1 + 2
```Thân lp thc thi ngay lp tc khi câu lnh lp chy.

## 6.25 Ví dụ từ đầu đến cuối

Hãy xem xét:```python
x = 10

def add(y):
    return x + y

print(add(5))
```Đường ng là:```text
tokenize source
parse tokens
build AST
analyze symbols
compile module code object
execute module frame
    bind x = 10
    create function object add
    bind add
    load print
    load add
    load 5
    call add
        create function frame
        bind y = 5
        load global x
        load local y
        add objects
        return 15
    call print
finish module execution
```Đim quan trng là CPython đã thc hin được công vic đáng k trước khi dòng đầu tiên xut hin để chy.

## 6.26 Nơi mỗi giai đoạn tồn tại

Mt bn đồ ngun hu ích:```text
Tokenizer          Parser/
Parser             Parser/ and Grammar/
AST support        Python/ast.c
Symbol table       Python/symtable.c
Compiler           Python/compile.c
Code objects       Objects/codeobject.c
Function objects   Objects/funcobject.c
Frames             Python/ and Objects/frameobject.c
Evaluation loop    Python/ceval.c and generated/interpreter files
Objects            Objects/
Imports            Lib/importlib/ and Python/import.c
```Tên tp chính xác thay đổi theo thi gian, nhưng bn đồ này đủ n định để đọc kho lưu tr.

## 6.27 Mô hình tinh thần

Gi mô hình nh gn này:```text
Source code becomes tokens.
Tokens become syntax.
Syntax becomes AST.
AST plus scope analysis becomes bytecode.
Bytecode lives in code objects.
Code objects execute inside frames.
Frames use local slots and a value stack.
Bytecode instructions operate on PyObject references.
Types decide concrete behavior.
```Toàn b h thng rt ln, nhưng trình t này là xương sng.

## 6.28 Tóm tắt chương

Vic thc thi CPython là mt đường dn. Nó bt đầu bng văn bn ngun và kết thúc bng các thao tác đối tượng bên trong b đánh giá mã byte. Trình mã thông báo x lý các ký t. Trình phân tích cú pháp x lý cú pháp. AST đại din cho cu trúc. Bng ký hiu phân loi tên. Trình biên dch phát ra các đối tượng mã. Các khung thc thi các đối tượng mã. Bytecode thao tác các đối tượng Python thông qua hành vi được xác định theo kiu.

Quy trình này gii thích cách các cu trúc Python cp cao tr thành các hành động thi gian chy c th.