31. Lệnh gọi hàm

Lệnh gọi hàm là một trong những đường dẫn thực thi quan trọng nhất trong CPython. Một cuộc gọi kết nối nhiều hệ thống cùng một lúc: thực thi mã byte, khung, liên kết đối số, bộ mô tả, phương thức, bao đóng, API C, đếm tham chiếu, ngoại lệ và xử lý trả về.

Một cuộc gọi đơn giản:python id="wauh11" result = f(1, 2) trông nhỏ ở cấp độ nguồn. Khi chạy, CPython phải:```text id="rhdr0d" load the callable load the arguments choose the correct call protocol bind arguments to parameters create or initialize a frame if calling Python code execute the callee return a result or propagate an exception store the result


## 31.1 Ý nghĩa của cuộc gọi

Trong Python, biu thc cuc gi có dng chung như sau:```python id="a7ltua"
callable_object(arguments)
```Đối tượng trước du ngoc đơn phi có th gi được.

Ví d:```python id="pqkmhl"
f()
len(xs)
obj.method(1)
C(10)
decorator(fn)
callback(event)
```Nhiu loi đối tượng có th được gi:

| Loi có th gi được | Ví d | Hành vi thi gian chy |
|---|---|---|
| Hàm Python |`f()`| To hoc khi to khung Python |
| Chc năng tích hp |`len(xs)`| Thc hin cuc gi C |
| Phương pháp ràng buc |`obj.method()`| Chc năng gi có gii hn`self`|
| Lp |`C()`| Đường dn xây dng siêu d liu cuc gi |
| Ví d có th gi được |`obj()`| Cuc gi`obj.__call__`|
| Hàm m rng C |`mod.func()`| Mã m rng cuc gi gc |
| Hàm coroutine |`async_fn()`| To đối tượng coroutine |
| Chc năng to |`gen()`| To đối tượng máy phát đin |
| Kết qu mô t |`obj.attr()`| Có th ràng buc trước cuc gi |

Cú pháp là thng nht. Đường dn thi gian chy ph thuc vào loi đối tượng có th gi được.

## 31.2 Mã byte cuộc gọi

Cuc gi biên dch thành mã byte ti mt lnh gi có th gi và các đối s ca nó, sau đó thc thi lnh gi.

Vì:```python id="xszy0u"
def g(a, b):
    return f(a, b)
```V mt khái nim:```text id="gwqjm5"
LOAD_GLOBAL f
LOAD_FAST a
LOAD_FAST b
CALL 2
RETURN_VALUE
```Ngăn xếp trước cuc gi cha các đối s và có th gi được:```text id="rc6gwy"
[f, a, b]
```Lnh gi tiêu th chúng và đẩy giá tr tr v:```text id="q4x2va"
[result]
```Trình t hướng dn chính xác thay đổi tùy theo phiên bn Python. CPython hin đại đã thay đổi giao thc cuc gi nhiu ln để ci thin hiu sut. Khái nim n định là:```text id="oc3h6f"
prepare callable and arguments
perform call
push result or raise exception
```## 31.3 Bố cục ngăn xếp cuộc gọi

Lnh gi cn có b cc ngăn xếp. B cc đơn gin hóa cho các lnh gi v trí là:```text id="2dz11l"
callable
arg0
arg1
arg2
...
```Vì:```python id="n90xfk"
f(x, y, z)
```ngăn xếp trước cuc gi v mt khái nim:```text id="0zk4e7"
[f, x, y, z]
```Sau cuc gi:```text id="1ef6n3"
[result]
```Cuc gi t khóa cn siêu d liu b sung.```python id="zewq6w"
f(x, y=10)
```V mt khái nim, CPython phi đại din cho:```text id="c35rsw"
callable = f
positional args = [x]
keyword names = ["y"]
keyword values = [10]
```CPython hin đại c gng th hin điu này mà không cn xây dng các b d liu và t đin tm thi khi có th.

## 31.4 Thứ tự đánh giá đối số

Python đánh giá các thành phn cuc gi theo th t xác định.

Vì:```python id="r11rqm"
f(a(), b(), c())
```các cuc gi xy ra t trái sang phi:```text id="rg0lon"
evaluate f
evaluate a()
evaluate b()
evaluate c()
call f with the three results
```Nếu như`b()`tăng,`c()`không chy.

Điu này quan trng vì các biu thc đối s có th có tác dng ph:```python id="9b37sl"
f(print("a"), print("b"))
```Vòng đánh giá phi duy trì th t cp ngun ca Python trong khi s dng ngăn xếp cho các giá tr tm thi.

## 31.5 Đối số vị trí

Mt hàm Python đơn gin:```python id="55c6o4"
def add(a, b):
    return a + b
```có hai tham s v trí.

Gi:```python id="wkxmb9"
add(2, 3)
```ràng buc:```text id="jlsbey"
a = 2
b = 3
```Trong CPython, khung callee s dng các khe cc b nhanh.

V mt khái nim:```text id="6u63lj"
callee frame localsplus:
    slot 0: a = 2
    slot 1: b = 3
```Sau đó, mã byte thc thi:```text id="chrvpi"
LOAD_FAST a
LOAD_FAST b
BINARY_OP +
RETURN_VALUE
```Bước ràng buc là mt phn chính ca chi phí cuc gi.

## 31.6 Đối số từ khóa

Đối s t khóa liên kết theo tên.```python id="n28umo"
def area(width, height):
    return width * height

area(height=10, width=20)
```Các đối s đến không theo th t tham s, nhưng các khe callee phi được đin chính xác:```text id="j16i8j"
width  = 20
height = 10
```CPython phi kim tra:```text id="x7xbwk"
whether each keyword matches a parameter
whether the same parameter was supplied twice
whether required parameters are missing
whether unexpected keywords should be rejected or collected by **kwargs
```Li ví d:```python id="rbyfsw"
area(20, width=10)
```Ngun cung cp này`width`hai ln: mt ln theo v trí và mt ln theo t khóa.

## 31.7 Đối số mặc định

Đối s mc định được lưu tr trên đối tượng hàm, không được to li trong mi lnh gi.```python id="d2kqmt"
def f(x, step=1):
    return x + step
```Đối tượng hàm lưu tr giá tr mc định cho`step`.

V mt khái nim:```text id="zw5t1r"
function f
    code object
    globals
    defaults: (1,)
```Khi được gi là:```python id="24ks4e"
f(10)
```CPython đin:```text id="n9k9rw"
x = 10
step = 1
```Hành vi mc định có th thay đổi ni tiếng sau đây:```python id="kjt1ip"
def append_item(x, xs=[]):
    xs.append(x)
    return xs
```Đối tượng danh sách được lưu tr trong hàm mc định và được s dng li trong các cuc gi.

## 31.8 Đối số chỉ từ khóa

Các thông s ch có t khóa phi được cung cp theo t khóa.```python id="53ae7c"
def connect(host, *, timeout, retries=3):
    ...
```Có hiu lc:```python id="kjp0p3"
connect("example.com", timeout=10)
```Không hp l:```python id="g6g3ha"
connect("example.com", 10)
```Đối tượng mã chc năng lưu tr siêu d liu v s lượng và b cc. Trong quá trình liên kết đối s, CPython s dng siêu d liu này để quyết định v trí cc b nhanh nào nhn giá tr.

V mt khái nim:```text id="w1u0wk"
positional slots
keyword-only slots
*args slot, if present
**kwargs slot, if present
```## 31.9 Đối số vị trí đa dạng

A`*args`tham s thu thp các đối s v trí b sung.```python id="hggzqm"
def f(a, *args):
    return args
```Gi:```python id="ve43p4"
f(1, 2, 3)
```ràng buc:```text id="72r8al"
a = 1
args = (2, 3)
```CPython to mt b d liu cho các đối s v trí b sung. Nếu không có đối s b sung nào được truyn, nó s s dng mt b d liu trng.

các`*args`slot vn là mt slot biến cc b thông thường theo quan đim ca mã byte.

## 31.10 Đối số từ khóa đa dạng

A`**kwargs`tham s thu thp các đối s t khóa b sung.```python id="842uzh"
def f(a, **kwargs):
    return kwargs
```Gi:```python id="e27hzk"
f(1, x=2, y=3)
```ràng buc:```text id="z7vjci"
a = 1
kwargs = {"x": 2, "y": 3}
```CPython to mt t đin cho các đối s t khóa chưa khp.

Nếu chc năng không có`**kwargs`, các đối s t khóa không mong mun là li.

## 31.11 Đối số cuộc gọi được gắn dấu sao

Mt cuc gi có th gii nén các đối s v trí:```python id="2t6bo9"
args = (1, 2)
f(*args)
```CPython phi đánh giá`args`, lp li hoc chuyn đổi nó thành đối s v trí, sau đó hp nht nó vào cuc gi.

Cho phép gii nén nhiu ln:```python id="dlam5o"
f(0, *xs, *ys)
```Thi gian chy phi duy trì th t t trái sang phi.

V mt khái nim:```text id="g86xe4"
positional arguments =
    [0] + list(xs) + list(ys)
```Nếu mt đối tượng được gii nén không th lp li được, CPython s tăng`TypeError`.

## 31.12 Đối số cuộc gọi được gắn dấu sao kép

Đối s t khóa có th được gii nén khi ánh x:```python id="gst2dz"
kwargs = {"x": 1, "y": 2}
f(**kwargs)
```Nhiu ánh x có th được cung cp:```python id="1obqtk"
f(**a, **b)
```CPython phi kim tra xem khóa có phi là chui khi gi hàm Python theo cách thông thường không và phi phát hin vic gán t khóa trùng lp.

Ví d:```python id="xha3n8"
f(x=1, **{"x": 2})
```Đây là mt li vì`x`được cung cp hai ln.

## 31.13 Lỗi liên kết đối số

Nhiu li cuc gi xy ra trước khi phn thân hàm bt đầu.

Ví d:```python id="fou3a6"
def f(a, b):
    pass

f(1)
f(1, 2, 3)
f(a=1, c=2)
f(1, a=2)
```Nhng nâng cao`TypeError`.

Vòng đánh giá bt đầu cuc gi nhưng máy gi thc hin kim tra ràng buc.

Mt cuc gi có th tht bi  mt s giai đon:```text id="1fh4l4"
callable lookup fails
argument expression raises
argument unpacking fails
object is not callable
argument binding fails
callee body raises
return handling fails indirectly through cleanup
```## 31.14 Lệnh gọi hàm Python

Đối vi lnh gi hàm Python thông thường, CPython chun b trng thái thc thi khung mi.```python id="u6ew7w"
def f(a, b):
    c = a + b
    return c
```Gi:```python id="ry7s81"
f(2, 3)
```V mt khái nim:```text id="kdm5oh"
function object:
    code object
    globals
    defaults
    closure

call:
    bind a = 2
    bind b = 3
    allocate or initialize frame
    run evaluation loop
    return result
```Khung mi tr ti cùng mt đối tượng mã trong mi cuc gi, nhưng các v trí cc b khác nhau đối vi mi cuc gi.

## 31.15 Lệnh gọi hàm tích hợp

Các hàm dng sn được trin khai trong C.```python id="47h9j2"
len(xs)
```Cuc gi không to khung Python cho phn thân ca`len`. Thay vào đó, CPython gi hàm C.

V mt khái nim:```text id="v2dcxi"
LOAD_GLOBAL len
LOAD_FAST xs
CALL 1
    call C implementation of len
push result
```Vic trin khai C vn nhn các đối tượng Python và tr v mt đối tượng Python.

Vì`len(xs)`, nó có th gi khe độ dài ca đối tượng và tr v s nguyên Python.

Các phn mm tích hp nhanh mt phn vì chúng tránh được vic thc thi mã byte Python cho phn thân ca chúng.

## 31.16 Lệnh gọi hàm mở rộng C

Các hàm m rng C tuân theo các nguyên tc tương t như các hàm dng sn.

Hàm m rng C nhn các đối s dưới dng đối tượng Python, xác thc chúng, thc hin công vic gc và tr v đối tượng Python hoc báo hiu mt ngoi l.

Hình ch C khái nim:```c id="fugpzb"
static PyObject *
mod_func(PyObject *self, PyObject *args)
{
    int x;

    if (!PyArg_ParseTuple(args, "i", &x)) {
        return NULL;
    }

    return PyLong_FromLong(x + 1);
}
```Các hàm m rng hin đại có th s dng các quy ước gi nhanh hơn để tránh đóng gói các đối s vào mt b d liu.

Bt k quy ước, quy tc là:```text id="1edgq5"
return PyObject* on success
return NULL with exception set on failure
```Vòng đánh giá kim tra kết qu.

## 31.17 Vectorcall

Vectorcall là quy ước gi nhanh ca CPython dành cho nhiu loi có th gi được.

Mc đích ca nó là truyn các đối s dưới dng mt mng C gm`PyObject *`giá tr thay vì luôn xây dng các đối tượng tuple và dict tm thi.

V mt khái nim:```text id="y0ul2m"
old-style call:
    build args tuple
    build kwargs dict
    call function

vectorcall-style:
    pass pointer to argument array
    pass argument count
    pass keyword names separately
    call function
```Điu này làm gim vic phân b và sao chép trên các đường dn cuc gi nóng.

Đối vi mt cuc gi như:```python id="i9fxmj"
f(a, b, c)
```các đối s có th đã nm lin k trên ngăn xếp trình thông dch. Vectorcall cho phép CPython chuyn trc tiếp vùng ging mng đó sang phn trin khai có th gi được.

## 31.18 Cuộc gọi và phương thức ràng buộc

Cuc gi phương thc cn ràng buc.```python id="yvl8kj"
obj.method(10)
``` cp độ ngôn ng, điu này có nghĩa là:```text id="ztwg7z"
look up method on obj
bind obj as self
call method with self and 10
```Nếu như`method`là mt hàm được định nghĩa trên lp, vic truy cp nó thông qua mt th hin s to ra mt phương thc ràng buc v mt khái nim:```python id="t8uh02"
bound = obj.method
bound(10)
```Phương thc ràng buc mang:```text id="qceh4k"
function
self object
```Sau đó gi nó là vt tư`self`t động.

CPython ti ưu hóa các lnh gi phương thc ph biến để tránh to đối tượng phương thc b ràng buc tm thi khi phương thc đó được gi ngay lp tc.

## 31.19 Liên kết mô tả

Các cuc gi phương thc da trên giao thc mô t.

Mt hàm được lưu tr trên mt lp là mt b mô t. Khi được truy cp thông qua mt th hin, nó`__get__`hành vi to ra mt phương pháp ràng buc.

Ví d:```python id="bkvw5y"
class C:
    def f(self, x):
        return x

obj = C()
obj.f(10)
```V mt khái nim:```text id="42zlm9"
C.__dict__["f"].__get__(obj, C)
    returns bound method
bound method called with x = 10
```Đây là lý do ti sao:```python id="pmz8uo"
C.f(obj, 10)
```cũng hot động.  dng đó, không có ràng buc cá th t động nào xy ra thông qua quyn truy cp thuc tính cá th. Bn vượt qua`obj`mt cách rõ ràng.

## 31.20 Cuộc gọi lớp

Vic gi mt lp s to hoc khi to mt th hin.```python id="0bc8io"
obj = C(1, 2)
```Mt lp có th gi được vì siêu d liu ca nó có th gi được. Thông thường siêu d liu là`type`.

Dòng khái nim:```text id="wy9ffx"
C.__call__(*args, **kwargs)
    calls C.__new__(C, *args, **kwargs)
    if result is instance of C:
        calls result.__init__(*args, **kwargs)
    returns result
```Ví d:```python id="j7g0io"
class C:
    def __new__(cls, value):
        obj = super().__new__(cls)
        return obj

    def __init__(self, value):
        self.value = value
```cuc gi`C(10)`không ch đơn thun là s phân b. Đó là mt giao thc liên quan đến`__new__`, `__init__`và hành vi siêu d liu.

## 31.21 Phiên bản có thể gọi được

Mt đối tượng có th gi được nếu kiu ca nó xác định`__call__`.

```python id="jv1zpx"
class Adder:
    def __init__(self, n):
        self.n = n

    def __call__(self, x):
        return self.n + x

add10 = Adder(10)
print(add10(5))
```Cuc gi:```python id="f9obht"
add10(5)
```gi mt cách khái nim:```python id="o2fo9r"
type(add10).__call__(add10, 5)
``` cp độ CPython, loi đối tượng cung cp hành vi cuc gi thông qua các v trí loi.

## 31.22 Trang trí và lời gọi

Trình trang trí được thc thi ti thi đim định nghĩa hàm.```python id="hxiutv"
@decorator
def f():
    pass
```V mt khái nim:```python id="57azij"
def f():
    pass

f = decorator(f)
```Lnh gi trang trí xy ra trong khi thc thi mô-đun, lp hoc ni dung hàm cha.

Nhiu trang trí:```python id="ew1w3e"
@d1
@d2
def f():
    pass
```nghĩa là:```python id="hq0xkt"
f = d1(d2(f))
```Điu này quan trng vì trang trí là các lnh gi thông thường. H có th tr v bt k đối tượng có th gi được hoc không th gi được.

## 31.23 Cuộc gọi và Kết thúc

Lnh gi đóng mang các biến đã được ghi li thông qua các đối tượng ô.```python id="ld9q93"
def outer(x):
    def inner(y):
        return x + y
    return inner

f = outer(10)
f(5)
```chc năng`inner`có:```text id="bmsuz9"
code object
globals
closure tuple containing cell for x
```Khi được gi, khung ca nó có th truy cp`x`thông qua tế bào đóng ca.

V mt khái nim:```text id="lojpq8"
inner frame:
    local y = 5
    free variable x -> cell -> 10
```Đường dn cuc gi thiết lp các đối s thông thường và cũng hin th các ô đóng đối vi`LOAD_DEREF`.

## 31.24 Cuộc gọi và Trình tạo

Vic gi hàm to không chy phn thân ca nó ngay lp tc.```python id="1wn1lz"
def gen():
    yield 1

g = gen()
```Cuc gi to ra mt đối tượng máy phát đin.

Phn thân hàm khi động khi trình to được ni li:```python id="xvobsw"
next(g)
```V mt khái nim:```text id="1gh51l"
call generator function:
    create generator object with suspended frame
    return generator

next(generator):
    resume frame
    execute until yield or return
```Đây là đim khác bit ln so vi các lnh gi hàm thông thường.

## 31.25 Cuộc gọi và Coroutine

Vic gi hàm async s to ra mt đối tượng coroutine.```python id="z4c0rv"
async def fetch():
    return 1

coro = fetch()
```Phn thân thường không chy đến mc hoàn thành vào thi đim gi. Nó chy khi được ch đợi hoc lên lch.```python id="tmq7yx"
result = await coro
```V mt khái nim:```text id="3o4iuh"
call async function:
    create coroutine object
    return coroutine

await coroutine:
    execute or resume coroutine frame
```Cuc gi hàm to ra đối tượng thc thi. Đang ch thc thi  đĩa.

## 31.26 Cuộc gọi đệ quy

Cuc gi đệ quy to nhiu khung hot động cho cùng mt đối tượng mã.```python id="mmzccu"
def fact(n):
    if n <= 1:
        return 1
    return n * fact(n - 1)
```Vì`fact(4)`:

```text id="v16tkx"
fact frame: n = 4
    fact frame: n = 3
        fact frame: n = 2
            fact frame: n = 1
```Mi khung có trng thái ngăn xếp và cc b nhanh riêng bit.

CPython kim tra độ sâu đệ quy để ngăn chn đệ quy không kim soát được làm cn kit tài nguyên thi gian chy.

## 31.27 Lệnh gọi và ngoại lệ

Cuc gi có th thoát bng cách quay li hoc nâng lên.```python id="zv234y"
def f():
    raise ValueError("bad")

def g():
    return f()
```Khi`f`tăng lên, nó không đẩy giá tr tr v bình thường. Ngoi l lan truyn qua ngăn xếp cuc gi.

V mt khái nim:```text id="p6uolo"
frame g calls frame f
frame f raises ValueError
frame f unwinds
frame g receives exception instead of return value
frame g unwinds unless it handles the exception
```Nếu như`g`có mt trình x lý:```python id="g7gg6a"
def g():
    try:
        return f()
    except ValueError:
        return 0
```ngoi l b bt trong`g`và vic thc thi bình thường s tiếp tc  trình x lý.

## 31,28 Giá trị trả về

Mi hàm Python đều tr v mt giá tr.

Nếu không tn ti giá tr tr v rõ ràng, nó s tr v`None`.

```python id="46x94k"
def f():
    pass
```V mt khái nim:```text id="99ydts"
LOAD_CONST None
RETURN_VALUE
```Mt biu thc cuc gi luôn mong đợi:```text id="q8p8m0"
a returned Python object
or an exception
```Không có kết qu bình thường th ba.

## 31.29 Quyền sở hữu tham chiếu trong các cuộc gọi

Các cuc gi có tính cht tham chiếu.

Trong cuc gi, CPython phi duy trì hot động:```text id="hinb3j"
callable object
argument objects
keyword name objects
temporary bound method state
callee frame
return value
exception objects, if any
```Lnh gi phi gii phóng các tham chiếu tm thi sau khi cuc gi thành công hoc tht bi.

Đường dn cuc gi được đơn gin hóa:```c id="s4hvbw"
result = PyObject_Call(callable, args, kwargs);
if (result == NULL) {
    goto error;
}
push(result);
```Nhưng trước và sau điu này, trình thông dch phi dn sch các tham chiếu đối s và xếp chng các mc mt cách chính xác.

Vic x lý tham chiếu không tt trong đường dn cuc gi có th làm rò r các đối s hoc phá hy các đối tượng vn đang được s dng.

## 31.30 Cuộc gọi có thể nhập lại Python

Mt lnh gi bên trong mt khung có th chy mã Python tùy ý.

Điu này hin nhiên đối vi các lnh gi hàm Python trc tiếp, nhưng cũng đúng đối vi các thao tác không ging các lnh gi.

Ví d:```python id="yv3kfl"
obj.x
```có th gi`obj.__getattribute__`.

Ví d:```python id="44ak0w"
a + b
```có th gi`a.__add__`.

Ví d:```python id="72yoig"
for x in xs:
    ...
```có th gi các phương thc lp.

Vì vy, trình thông dch phi gi định rng nhiu thao tác có th thc thi li Python.

Ngăn xếp cuc gi có th phát trin t các cuc gi rõ ràng hoc n:```text id="5p626a"
frame A
    executes LOAD_ATTR
        calls Python descriptor
            frame B
```## 31.31 Tối ưu hóa cuộc gọi phương thức

Mu ngun này là ph biến:```python id="8wm8xu"
obj.method(arg)
```Vic trin khai ngây thơ s:```text id="ywi46w"
load obj
load method attribute
create bound method object
load arg
call bound method
destroy bound method object
```CPython ti ưu hóa điu này bng cách nhn dng các mu lnh gi phương thc ph biến.

Đường dn được ti ưu hóa tránh phân b phương thc ràng buc tm thi khi có th:```text id="d28yc3"
load method function and self separately
call function with self and arguments
```Điu này làm gim lưu lượng phân b và s lượng tham chiếu.

Hành vi ngôn ng không thay đổi. Vic ti ưu hóa ch thay đổi đường dn cuc gi ni b.

## 31.32 Cuộc gọi và bộ đệm nội tuyến

Mã byte cuc gi có th s dng b đệm ni tuyến.

Mt trang cuc gi thường thy cùng mt cuc gi lp đi lp li:```python id="on96mz"
for x in xs:
    total += f(x)
```Lnh gi ti v trí ngun này có th liên tc gi cùng mt chc năng`f`.

CPython có th lưu tr thông tin như:```text id="ec11pe"
callable type
function version
argument shape
method lookup result
global lookup version
descriptor result
```Nếu lính canh vượt qua, thông dch viên có th s dng đường dn nhanh.

Nếu có th gi thay đổi, nó s quay tr li hành vi chung.

## 31.33 Cuộc gọi và Chuyên môn

Chuyên môn hóa có th ti ưu hóa mã nng cuc gi.

Ví d:```python id="sky0ma"
def loop(xs):
    total = 0
    for x in xs:
        total += int(x)
    return total
```Trang web cuc gi cho`int(x)`có th tr nên chuyên bit nếu nó liên tc nhìn thy cùng mt hình dng đối s và có th gi được.

Chuyên môn hóa không thay đổi ng nghĩa Python. Nó ch tăng tc các trường hp ph biến dưới s bo v.

Hp đồng ngăn xếp vn còn:```text id="nx4fmo"
before call: callable and arguments
after call: result
or exception
```## 31.34 Cuộc gọi và GIL

Trong CPython truyn thng, vic thc thi mã byte Python xy ra trong khi gi GIL.

Lnh gi ti mã Python vn tiếp tc trong mô hình đó.

Lnh gi ti mã C có th gii phóng GIL nếu vic trin khai C chn thc hin như vy đối vi công vic kéo dài.

Ví d v mã C có th gii phóng GIL:```text id="99b4lz"
blocking I/O
compression
hashing
numeric kernels
database drivers
system calls
```Điu này có nghĩa là mt cuc gi có th tm thi cho phép mt lung Python khác chy nếu callee là mã gc gii phóng GIL.

Đối vi các lnh gi Python thun túy, vic thc thi mã byte vn được GIL tun t hóa trong các bn dng truyn thng.

## 31.35 Cuộc gọi và Phương thức dựng sẵn

Các phương thc dng sn thường là các b mô t cp độ C.

Ví d:```python id="lz9y2o"
xs.append(1)
```phương pháp`append`được trin khai trong C cho các đối tượng danh sách.

Đường dn được ti ưu hóa cao có th tránh to đối tượng phương thc ràng buc Python và gi trc tiếp vic trin khai ni thêm danh sách.

Cuc gi cp ngun:```python id="bx4yzs"
xs.append(1)
```do đó bao gm:```text id="2d6rn4"
attribute or method resolution
argument setup
C method call
mutation of list object
return None
```Nó nhanh hơn nhiu so vi mt phương thc tương đương được trin khai trong Python vì logic vòng lp và đột biến chy trong C.

## 31.36 Cuộc gọi và`super`

`super()`là mt đối tượng có th gi và nhn biết mô t, thay đổi độ phân gii ca phương thc.```python id="xskypw"
class Base:
    def f(self):
        return 1

class Child(Base):
    def f(self):
        return super().f() + 1
```Cuc gi:```python id="onpk7n"
super().f()
```liên quan đến:```text id="s1yqxl"
create or resolve super object
perform attribute lookup using adjusted MRO position
bind method to original instance
call method
```Đây là máy gi thông thường cng vi độ phân gii thuc tính đặc bit.

## 31.37 Lệnh gọi và Thuộc tính

Quyn truy cp thuc tính có th gi mã trước khi cuc gi rõ ràng bt đầu.```python id="utkq7j"
obj.factory()
```Nếu như`factory`là mt tài sn:```python id="q5y4ib"
class C:
    @property
    def factory(self):
        return lambda: 42
```Sau đó:```text id="7onci0"
obj.factory
    calls property getter
    returns callable

(...)
    calls returned callable
```Vì vy, biu thc ngun cha mt lnh gi n theo sau là mt lnh gi rõ ràng.

Đây là lý do ti sao CPython phi coi quyn truy cp thuc tính là có hiu qu.

## 31.38 Dọn dẹp cuộc gọi và lỗi

Gi s lnh gi này đánh giá mt phn các đối s, sau đó không thành công:```python id="xwgmze"
f(g(), h())
```Nếu như`h()`tăng thì:```text id="9lvmys"
f has been loaded
g() has returned
h() raises
the call to f never happens
temporaries must be cleaned up
exception propagates
```Ngăn xếp có th cha các tham chiếu tm thi ti`f`Và`g()`kết qu ca. CPython phi gii phóng chúng mt cách chính xác trong quá trình g li.

Đây là mt trong nhng lý do khiến đường dn li mã byte và vòng lp đánh giá phi cn thn.

## 31.39 Kiểm tra cuộc gọi

s dng`dis`để kim tra mã byte cuc gi.```python id="rgh73f"
import dis

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

def caller(x):
    return target(x, 10)

dis.dis(caller)
```Kim tra siêu d liu chc năng:```python id="i0pt0v"
print(target.__code__.co_argcount)
print(target.__code__.co_posonlyargcount)
print(target.__code__.co_kwonlyargcount)
print(target.__defaults__)
print(target.__kwdefaults__)
print(target.__code__.co_varnames)
```Kim tra ch ký  cp độ Python:```python id="dcrnsg"
import inspect

print(inspect.signature(target))
```các`inspect`chế độ xem  cp độ ngun và thân thin vi người dùng. Chế độ xem đối tượng mã gn vi nhng gì CPython s dng để thiết lp khung.

## 31.40 Phiên dịch cuộc gọi tối thiểu

Mt thông dch viên đồ chơi có th hin th mô hình cuc gi.```python id="47u5eu"
LOAD_CONST = "LOAD_CONST"
LOAD_FAST = "LOAD_FAST"
CALL = "CALL"
RETURN = "RETURN"

def run(code, consts, locals_):
    stack = []

    for op, arg in code:
        if op == LOAD_CONST:
            stack.append(consts[arg])

        elif op == LOAD_FAST:
            stack.append(locals_[arg])

        elif op == CALL:
            argc = arg
            args = stack[-argc:]
            del stack[-argc:]

            func = stack.pop()
            result = func(*args)
            stack.append(result)

        elif op == RETURN:
            return stack.pop()

    raise RuntimeError("missing RETURN")
```Chương trình:```python id="lq4boa"
def add(a, b):
    return a + b

code = [
    (LOAD_CONST, 0),   # add
    (LOAD_FAST, "x"),
    (LOAD_CONST, 1),   # 10
    (CALL, 2),
    (RETURN, None),
]

print(run(code, [add, 10], {"x": 5}))
```Đầu ra:```text id="5boj0q"
15
```Điu này b qua ràng buc đối s thc, b mô t, API C, ngoi l, khung, lnh gi vector và tính tham chiếu ca Python. Nó vn nm bt được ý tưởng ngăn xếp: mt cuc gi s dng các đối s và có th gi được, sau đó đưa ra mt kết qu.

## 31.41 Những hiểu lầm phổ biến

| Hiu lm | Đúng mu |
|---|---|
| Cuc gi luôn to khung Python | Các hàm dng sn và hàm C không to khung Python cho phn thân ca chúng |
| Gi mt hàm async s chy nó ngay lp tc | Nó to ra mt đối tượng coroutine |
| Vic gi hàm to s chy cho đến khi mang li li nhun đầu tiên | Nó to ra mt đối tượng máy phát đin |
| Các phương thc luôn phân b các đối tượng phương thc b ràng buc | CPython thường tránh điu này đối vi các cuc gi ngay lp tc |
| Đối s t khóa luôn được truyn dưới dng lnh | Đường dn nhanh có th tránh vic xây dng mt lnh |
|`def`ch khai báo mt hàm |`def`thc thi và to mt đối tượng hàm |
| Các lp không phi là hàm nên chúng không th gi được | Các lp có th gi được thông qua logic siêu d liu |
|`obj()`phi là mt cuc gi hàm | Nó có th gi`type(obj).__call__`|

## 31.42 Chiến lược đọc

Để nghiên cu các cuc gi, hãy bt đầu vi các biu mu ngun đơn gin:```python id="s1he1e"
f()
f(a, b)
f(a=1)
f(*args)
f(**kwargs)
obj.method(x)
C(x)
async_fn()
gen_fn()
```Đối vi mi người:```python id="cvm0yb"
import dis
dis.dis(function_containing_call)
```Sau đó hi:```text id="8l87gs"
How is the callable loaded?
How are arguments loaded?
Are keywords present?
Is unpacking present?
Does attribute lookup happen before the call?
Does binding happen?
Does the call create a Python frame?
Can the call return a coroutine or generator instead of running the body?
What cleanup is needed if argument evaluation fails?
```Cách tiếp cn này biến cú pháp cuc gi thành các hot động thông dch c th.

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

Lnh gi hàm trong CPython là mt hot động thi gian chy có cu trúc. Trình thông dch đánh giá kh năng gi và đối s, sp xếp chúng trên ngăn xếp khung, chn giao thc gi thích hp, liên kết các đối s khi cn, thc thi khung Python hoc trin khai C gc, sau đó đẩy mt đối tượng được tr v hoc truyn mt ngoi l.

Mô hình trung tâm là:```text id="oiwfbx"
load callable
load arguments
CALL
    bind arguments
    run Python frame or native callable
    return object or raise exception
store or use result
```Các cuc gi rt tn kém vì chúng vượt qua nhiu ranh gii thi gian chy: b cc ngăn xếp, liên kết đối s, liên kết mô t, thiết lp khung, quy ước API C, quyn s hu tham chiếu, x lý ngoi l và chuyên môn hóa.

Phn ln công vic v hiu sut ca CPython tp trung vào vic thc hin các cuc gi r hơn mà không thay đổi ng nghĩa động ca Python.