#9. Đếm tham khảo

Tính tham chiếu là cơ chế quản lý bộ nhớ chính của CPython. Mỗi đối tượng thông thường đều mang một số lượng tham chiếu mạnh hiện đang trỏ đến nó. Khi số lượng đó giảm xuống 0, CPython có thể phá hủy đối tượng ngay lập tức.

Thiết kế này là một trong những khác biệt rõ ràng nhất giữa CPython và nhiều thời gian chạy ngôn ngữ khác. CPython có một trình thu thập rác theo chu kỳ, nhưng trình thu thập này bổ sung tính năng tham chiếu. Hầu hết các đối tượng được lấy lại bằng cách chuyển đổi số tham chiếu chứ không phải bằng cách theo dõi định kỳ.

9.1 Ý tưởng cốt lõi

Một đối tượng Python vẫn tồn tại trong khi có thứ gì đó sở hữu một tham chiếu đến nó.

Về mặt khái niệm:```text object created reference count = 1

another owner stores the object reference count += 1

an owner releases the object reference count -= 1

reference count reaches 0 object is deallocated Ví dụ:python x = [] y = x

del x del y ```Đối tượng danh sách được tạo và liên kết vớix. Ràng buộcy = xtạo một tham chiếu khác tới cùng danh sách. Đang xóaxloại bỏ một tham chiếu. Đang xóayloại bỏ tham chiếu còn lại, do đó danh sách có thể bị hủy.

Ở cấp độ C, điều này được kiểm soát bởi tiêu đề đối tượng:```c typedef struct { Py_ssize_t ob_refcnt; PyTypeObject *ob_type; } PyObject;


`ob_refcnt`là trường đếm tham chiếu.

## 9.2 Tài liệu tham khảo mạnh

Mt tham chiếu mnh gi cho mt đối tượng tn ti.

Hu hết các liên kết Python thông thường đều là các tham chiếu mnh:```python
x = object()
items = [x]
d = {"key": x}
``` đây, đối tượng có các tham chiếu t:```text
local name x
list element items[0]
dictionary value d["key"]
```Min là còn li ít nht mt tham chiếu mnh thì đối tượng không th b phá hy.

Các thùng cha cha các tham chiếu mnh đến các phn t ca chúng. Danh sách không lưu tr giá tr thô. Nó lưu tr các con tr ti các đối tượng Python và s hu các tham chiếu đến chúng.```python
a = []
b = [a]
```Danh sách`b`s hu mt tham chiếu đến danh sách`a`.

## 9.3 Tài liệu tham khảo mượn và tài liệu tham khảo sở hữu

 cp độ API C, vic đếm tham chiếu được kim soát bi các quy tc quyn s hu.

Có hai loi ph biến:

| Loi tham kho | Ý nghĩa |
| ------------------ | ---------------------------------------------------------------------- |
| Tài liu tham kho mi | Người gi s hu tham chiếu và phi gii phóng nó |
| Tài liu tham kho mượn | Người gi có th s dng đối tượng tm thi nhưng không s hu tài liu tham kho mi |

Ví d v mt tài liu tham kho mi:```c
PyObject *x = PyLong_FromLong(42);

/* x is a new reference */
Py_DECREF(x);

PyLong_FromLongtạo hoặc trả về một đối tượng và cấp cho người gọi quyền sở hữu một tham chiếu.

Ví dụ về một tài liệu tham khảo mượn:```c PyObject *item = PyList_GetItem(list, 0);

/* item is borrowed */ ```Người gọi không được gọiPy_DECREF(item)trừ khi trước tiên nó chuyển đổi tham chiếu mượn thành tham chiếu sở hữu vớiPy_INCREF.

Đúng mẫu:```c PyObject *item = PyList_GetItem(list, 0); if (item == NULL) { return NULL; }

Py_INCREF(item); /* now item is owned */

/* use item */

Py_DECREF(item);


## 9,4`Py_INCREF`

`Py_INCREF`ghi li rng mt ch s hu na hin đang nm gi mt tham chiếu mnh m.

V mt khái nim:```c
Py_INCREF(obj);
```có nghĩa:```text
I am going to keep this object alive.
```Các trường hp đin hình:```text
store object into a container
store object into a struct field
return an existing object as a new reference
keep a borrowed reference beyond its safe lifetime
```Ví d:```c
typedef struct {
    PyObject_HEAD
    PyObject *value;
} BoxObject;
```Nếu mt`BoxObject`lưu tr mt đối tượng Python khác, nó phi tăng s lượng tham chiếu:```c
static int
Box_set_value(BoxObject *self, PyObject *value)
{
    Py_INCREF(value);
    Py_XDECREF(self->value);
    self->value = value;
    return 0;
}
```Chiếc hp tr thành ch s hu ca`value`.

## 9,5`Py_DECREF`

`Py_DECREF`gii phóng quyn s hu ca mt tài liu tham kho.

V mt khái nim:```c
Py_DECREF(obj);
```có nghĩa:```text
I no longer need to keep this object alive.
```Nếu s tham chiếu bng 0, CPython s hy đối tượng.

Đơn gin hóa:```c
#define Py_DECREF(op)                  \
    do {                               \
        if (--(op)->ob_refcnt == 0) {  \
            dealloc(op);               \
        }                              \
    } while (0)
```Vic trin khai thc tế phc tp hơn, nhưng điu này nm bt được quy tc.

Mi tài liu tham kho mi cui cùng phi được phát hành.```c
PyObject *x = PyLong_FromLong(42);
if (x == NULL) {
    return NULL;
}

/* use x */

Py_DECREF(x);
```quên đi`Py_DECREF`làm rò r vt th.

Đang gi`Py_DECREF`quá nhiu ln có th phá hy mt đồ vt khi nó vn đang được s dng.

## 9,6`Py_XINCREF`Và`Py_XDECREF`Một số gợi ý có thể`NULL`.

`Py_INCREF`Và`Py_DECREF`yêu cu mt con tr đối tượng hp l. Ca h`X`biến th chp nhn`NULL`.

```c
Py_XINCREF(obj);
Py_XDECREF(obj);
```Chúng thường được s dng cho các trường tùy chn:```c
typedef struct {
    PyObject_HEAD
    PyObject *name;   /* may be NULL */
} UserObject;
```Người giao dch:```c
static void
User_dealloc(UserObject *self)
{
    Py_XDECREF(self->name);
    Py_TYPE(self)->tp_free((PyObject *)self);
}
```Nếu như`self->name`là`NULL`, `Py_XDECREF`không làm gì c

## 9.7 Bài tập ở cấp độ Python

Bài tp Python thay đổi các ràng buc.```python
x = []
x = {}
```Nhim v đầu tiên ràng buc`x`vào mt danh sách. Nhim v th hai tr li`x`đến mt mnh lnh.

 cp độ CPython, vic đóng li có nghĩa là:```text
increment reference to new object
store new pointer in local variable slot
decrement reference to previous object
```Th t quan trng. CPython phi tránh phá hy mt đối tượng quá sm, đặc bit khi các phép gán liên quan đến các tham chiếu chng chéo hoc đường dn li.

Ví d:```python
x = []
y = x
x = None
```Sau đó`x = None`, danh sách vn còn tn ti vì`y`vn đề cp đến nó.

## 9.8 Tài liệu tham khảo riêng của vùng chứa

Khi mt đối tượng được chèn vào vùng cha, vùng cha đó s s hu mt tham chiếu.```python
x = object()
items = []
items.append(x)
```Đối tượng được tham chiếu bi c hai`x`Và`items[0]`.

 cp độ C, vùng cha phi tăng s lượng tham chiếu khi lưu tr mt đối tượng.

Logic ni danh sách đơn gin hóa:```text
append item to list
    ensure capacity
    increment item reference count
    store item pointer
    increase list size
```Khi danh sách b hy, nó s gii phóng các tham chiếu đến các phn t ca nó:```text
destroy list
    for each item:
        decrement item reference count
    free item array
    free list object
```Mô hình s hu này có tính đệ quy. Vic phá hy mt vùng cha có th kích hot vic phá hy các đối tượng được cha nếu không có tham chiếu nào khác tn ti.

## 9.9 Thay thế tài liệu tham khảo một cách an toàn

Mu C ph biến đang thay thế mt trường thuc s hu bng mt trường khác.

Không đúng:```c
Py_DECREF(self->value);
self->value = new_value;
Py_INCREF(new_value);
```Điu này có th tht bi nếu`new_value`là cùng mt đối tượng như`self->value`. các`Py_DECREF`có th phá hy đối tượng trước khi s gia tăng xy ra.

Chính xác:```c
Py_INCREF(new_value);
Py_DECREF(self->value);
self->value = new_value;
```Đối vi các trường có giá tr rng:```c
Py_XINCREF(new_value);
Py_XDECREF(self->value);
self->value = new_value;
```Mu này đơn gin nhưng quan trng:```text
increment new reference first
decrement old reference second
store pointer when ownership is safe
```## 9.10 Ăn cắp tài liệu tham khảo

Mt s hàm API C ly cp tài liu tham kho.

Hàm đánh cp tham chiếu s chiếm quyn s hu t người gi. Sau khi gi thành công, người gi không được gim tham chiếu đó.

Mu ví d:```c
PyObject *value = PyLong_FromLong(42);
if (value == NULL) {
    return NULL;
}

if (PyTuple_SetItem(tuple, 0, value) < 0) {
    Py_DECREF(value);
    return NULL;
}

/* do not Py_DECREF(value) here */

PyTuple_SetItemđánh cắp một tài liệu tham khảo đếnvaluevề sự thành công.

Quy ước này tồn tại để mang lại hiệu quả, đặc biệt khi xây dựng các thùng chứa từ các đối tượng mới được tạo.

Ăn cắp tài liệu tham khảo là một nguồn lỗi thường xuyên. Quy tắc phải được đọc từ tài liệu API hoặc quy ước API C đã biết. Nó không thể được suy ra từ kiểu con trỏ đối tượng.

9.11 Đường dẫn lỗi

Lỗi đếm tham chiếu thường xảy ra trên các đường dẫn lỗi.

Ví dụ:```c PyObject *a = PyLong_FromLong(1); if (a == NULL) { return NULL; }

PyObject b = PyLong_FromLong(2); if (b == NULL) { return NULL; / leak: a was not released */ } Chính xác:c PyObject *a = PyLong_FromLong(1); if (a == NULL) { return NULL; }

PyObject *b = PyLong_FromLong(2); if (b == NULL) { Py_DECREF(a); return NULL; } Một phong cách phổ biến sử dụng một khối dọn dẹp:c PyObject *a = NULL; PyObject *b = NULL; PyObject *result = NULL;

a = PyLong_FromLong(1); if (a == NULL) { goto error; }

b = PyLong_FromLong(2); if (b == NULL) { goto error; }

result = PyNumber_Add(a, b); if (result == NULL) { goto error; }

Py_DECREF(a); Py_DECREF(b); return result;

error: Py_XDECREF(a); Py_XDECREF(b); return NULL;


## 9.12 Trả lại tài liệu tham khảo

Hàm C tiếp xúc vi Python thường tr v mt tham chiếu mi.

Ví d:```c
static PyObject *
answer(PyObject *self, PyObject *args)
{
    return PyLong_FromLong(42);
}
```Đối tượng được tr v là mt tham chiếu mi. Người thông dch nhn nó và chu trách nhim v nó.

Nếu tr v mt đối tượng hin có, hãy tăng trước:```c
static PyObject *
get_cached_value(MyObject *self, PyObject *Py_UNUSED(ignored))
{
    Py_INCREF(self->cached_value);
    return self->cached_value;
}
```Tr li mt tham chiếu đã mượn mà không tăng dn là mt li nghiêm trng:```c
static PyObject *
bad_get_cached_value(MyObject *self, PyObject *Py_UNUSED(ignored))
{
    return self->cached_value;   /* wrong if this is borrowed */
}
```Người gi mong đợi quyn s hu giá tr tr v. Nếu s lượng tham chiếu không được tăng lên thì các ln gim sau này có th làm gim quyn s hu và gây ra hành vi s dng sau khi không s dng.

## 9.13`None`, `True`, Và`False`Trở về`None`là phổ biến.

S dng:```c
Py_RETURN_NONE;
```V mt khái nim, điu này tăng lên`None`và tr li nó.

Hình dng tương đương:```c
Py_INCREF(Py_None);
return Py_None;
```Tương t:```c
Py_RETURN_TRUE;
Py_RETURN_FALSE;
```Nhng macro này tránh sai lm và làm cho ý định rõ ràng.

 cp độ Python:```python
def f():
    return None
``` cp độ C, hàm vn phi tr v mt tham chiếu s hu cho`None`s vt.

## 9.14 Tài liệu tham khảo tạm thời

Nhiu thao tác to ra các tham chiếu tm thi.

Ví d:```c
PyObject *a = PyLong_FromLong(10);
PyObject *b = PyLong_FromLong(20);
PyObject *sum = PyNumber_Add(a, b);
```Đây,`a`, `b`, Và`sum`đều là tài liu tham kho được s hu nếu vic to thành công.

Dn dp đúng cách:```c
Py_DECREF(a);
Py_DECREF(b);

return sum;
```Đừng gim`sum`trước khi tr li vì người gi s nhn được quyn s hu.

S phân chia này rt quan trng:```text
objects used temporarily inside the function
    DECREF before return

object returned to caller
    return as owned reference
```## 9.15 Số lượng tham chiếu và lệnh gọi hàm

Khi mt hàm Python được gi, các đối s s được truyn dưới dng tham chiếu đối tượng.```python
def f(x):
    return x

obj = []
y = f(obj)
```Đối tượng không được sao chép. Hàm nhn được mt tham chiếu đến cùng mt danh sách.

 cp độ trình thông dch, máy gi hàm qun lý các tham chiếu cho các đối tượng đối s, biến cc b, giá tr ngăn xếp và giá tr tr v.

V mt khái nim:```text
caller has reference to obj
call passes reference into callee frame
callee local x refers to same object
return value refers to same object
callee frame is cleared
caller receives returned reference
```Cơ chế chính xác được ti ưu hóa nhưng tính bt biến v quyn s hu vn được gi nguyên: mi tham chiếu trc tiếp đều phi được tính đến.

## 9.16 Tài liệu tham khảo ngăn xếp

Trình thông dch mã byte s dng ngăn xếp giá tr bên trong mi khung.

Hướng dn mã byte đẩy và bt các tham chiếu đối tượng.

Ví d:```python
a + b
```V mt khái nim:```text
LOAD_FAST a
    push reference to a

LOAD_FAST b
    push reference to b

BINARY_OP +
    pop two references
    compute result
    push result reference
```Các mc ngăn xếp là tài liu tham kho. Khi các giá tr được bt lên và không còn cn thiết na, CPython phi gii phóng các tham chiếu tương ng.

Do đó, vòng đánh giá là mt h thng qun lý tham chiếu ln. Nó phi bo toàn quyn s hu trong quá trình thc thi thông thường, ngoi l, nhy, tr v và phá b khung.

## 9.17 Đếm tham chiếu và ngoại lệ

X lý li yêu cu dn dp tham chiếu cn thn.

Gi s mt thao tác không thành công sau khi to các đối tượng tm thi:```c
PyObject *name = PyUnicode_FromString("field");
if (name == NULL) {
    return NULL;
}

PyObject *value = PyObject_GetAttr(obj, name);
Py_DECREF(name);

if (value == NULL) {
    return NULL;
}

return value;
```Nếu như`PyObject_GetAttr`tht bi, nó quay tr li`NULL`và đặt mt ngoi l. tm thi`name`vn phi được gim bt trước khi quay tr li.

Hàm C báo cáo mt ngoi l bng cách tr v`NULL`trong khi mt ngoi l được thiết lp.

Vic dn dp tham chiếu và truyn bá ngoi l là nhng trách nhim riêng bit:```text
release owned references
preserve or set exception state
return NULL
```## 9.18 Rò rỉ tham khảo

Rò r tham chiếu xy ra khi mt tham chiếu mnh không bao gi được phát hành.

Ví d:```c
static PyObject *
leaky(PyObject *self, PyObject *args)
{
    PyObject *x = PyLong_FromLong(42);
    if (x == NULL) {
        return NULL;
    }

    Py_RETURN_NONE;   /* leak: x was never DECREFed */
}
```Chính xác:```c
static PyObject *
fixed(PyObject *self, PyObject *args)
{
    PyObject *x = PyLong_FromLong(42);
    if (x == NULL) {
        return NULL;
    }

    Py_DECREF(x);
    Py_RETURN_NONE;
}
```Rò r tham chiếu có th nh nhưng nghiêm trng trong các quy trình chy dài:```text
web servers
workers
language servers
notebooks
daemon processes
embedded Python runtimes
```Rò r trên đường dn nóng có th phát trin không gii hn.

## 9.19 Sử dụng sau miễn phí

Vic s dng min phí xy ra khi mã s dng mt con tr sau khi đối tượng được tham chiếu đã b hy.

Mu ví d:```c
PyObject *item = PyList_GetItem(list, 0);  /* borrowed */

Py_DECREF(list);

/* item may now be invalid */
PyObject_Repr(item);
```Nếu như`list`s hu tài liu tham kho mnh m cui cùng v`item`, phá hy`list`cũng b phá hy`item`.

Chính xác:```c
PyObject *item = PyList_GetItem(list, 0);
if (item == NULL) {
    return NULL;
}

Py_INCREF(item);

Py_DECREF(list);

/* item is still alive */
PyObject *repr = PyObject_Repr(item);

Py_DECREF(item);
return repr;
```Các tham chiếu mượn không được tn ti lâu hơn ch s hu ca chúng tr khi được chuyn đổi thành các tham chiếu được s hu.

## 9,20 Chu kỳ

Vic tính tham chiếu mt mình không th ly li chu k.

Ví d:```python
a = []
b = []

a.append(b)
b.append(a)

del a
del b
```Sau khi xóa`a`Và`b`, hai danh sách vn tham chiếu ln nhau.

V mt khái nim:```text
list A ---> list B
list B ---> list A
```S lượng tham chiếu ca h không đạt ti 0, mc dù chương trình không th tiếp cn h được na.

Đây là lý do ti sao CPython có trình thu gom rác theo chu k. Nó tìm thy các nhóm đối tượng cha không th truy cp được và phá v chúng mt cách an toàn.

Tính tham chiếu x lý trường hp ph biến. GC tun hoàn x lý các trường hp đếm tham chiếu không th nhìn thy.

## 9.21 Công cụ hoàn thiện và thời gian hủy diệt

CPython thường phá hy các đối tượng ngay lp tc khi tham chiếu cui cùng ca chúng biến mt.

Ví d:```python
class Resource:
    def __del__(self):
        print("destroyed")

r = Resource()
del r
```Trong CPython,`__del__`thường chy ngay sau đó`del r`, gi s không có tài liu tham kho nào khác tn ti.

Nhưng mã Python di động nên tránh da vào thi gian hy chính xác. Các trin khai khác có th s dng các chiến lược thu gom rác khác nhau.

S dng trình qun lý bi cnh để qun lý tài nguyên xác định:```python
with open("data.txt") as f:
    data = f.read()
```Điu này tt hơn là da vào vic phá hy đối tượng tp:```python
f = open("data.txt")
data = f.read()
f = None
```Vic đếm tham chiếu giúp dn dp nhanh chóng CPython, nhưng`with`th hin trc tiếp cuc đời.

## 9.22 Số lượng tham chiếu có thể quan sát được nhưng cụ thể khi triển khai

CPython hin th s lượng tham chiếu thông qua`sys.getrefcount`.

```python
import sys

x = []
print(sys.getrefcount(x))
```Con s được báo cáo thường cao hơn d kiến ​​vì đã vượt qua`x`vào trong`getrefcount`to ra mt tham chiếu tm thi.

Ví d:```python
import sys

x = []
print(sys.getrefcount(x))   # often 2, not 1
```Mt tài liu tham kho là t tên địa phương`x`. Mt tham chiếu tm thi khác là t lnh gi hàm.

S dng công c này mt cách cn thn. Nó rt hu ích cho vic tìm hiu và g li hành vi CPython, nhưng nó tiết l chi tiết trin khai.

## 9.23 Vật thể bất tử

CPython hin đại s dng các đối tượng bt t cho các giá tr được chn nhm tn ti trong sut vòng đời ca quy trình.

Mt vt th bt t không hot động ging như mt vt th được k li thông thường theo nghĩa đơn gin. S tham chiếu ca nó có th s dng mt giá tr đặc bit và các hot động tăng hoc gim thông thường có th tránh làm thay đổi thi gian tn ti hiu qu ca nó.

Vic ti ưu hóa này giúp gim chi phí chung cho các đối tượng rt ph biến và đơn gin hóa mt s bt biến trong thi gian chy.

Các ví d quan trng bao gm các đối tượng cơ bn cho thi gian chy, chng hn như các giá tr ging như singleton và các đối tượng bên trong thường được s dng li.

Quy tc dành cho tác gi phn m rng vn đơn gin:```text
always use Py_INCREF, Py_DECREF, Py_XINCREF, and Py_XDECREF
do not inspect or modify ob_refcnt directly
do not assume reference counts are ordinary small integers
```Mã đúng hot động vi các vt th thông thường và bt t.

## 9.24 CPython có luồng miễn phí và tính toán tham chiếu

CPython truyn thng bo v nhiu bn cp nht s lượng tham chiếu bng Khóa phiên dch toàn cu. Trong các bn dng có lung t do, vic qun lý tham chiếu cn có máy móc b sung vì nhiu lung có th thc thi mã Python cùng mt lúc.

Điu này nh hưởng đến chi tiết trin khai ni b, nhưng quy tc quyn s hu API C vn là hp đồng khái nim:```text
own a new reference
    release it exactly once

borrow a reference
    do not release it

keep a borrowed reference longer
    increment it first
```Ni b có th s dng tính năng tham chiếu sai lch, x lý tham chiếu trì hoãn, hot động nguyên t hoc các k thut khác tùy thuc vào chế độ và phiên bn xây dng.

Mã m rng nên tránh da vào b cc s tham chiếu thô hoc cơ chế cp nht.

## 9.25 Kỷ luật đếm tham khảo

Mt nguyên tc thc tế cho mã m rng C:

| Tình hung | Hành động |
| ------------------------------------- | ----------------------------------------- |
| Hàm tr v mt tham chiếu mi |`Py_DECREF`khi hoàn thành |
| Hàm tr v mt tham chiếu đã mượn | Đừng`Py_DECREF`|
| Lưu tr đối tượng trong mt trường |`Py_INCREF`trước khi lưu tr |
| Thay thế đối tượng trong mt trường |`Py_INCREF`thì mi`Py_DECREF`cũ |
| Tr v đối tượng hin có |`Py_INCREF`trước khi quay li |
| Li sau khi ly tài liu tham kho | Phát hành các tài liu tham kho đã s hu trước khi quay li |
| Con tr có th`NULL`| S dng`Py_XDECREF`|
| API đánh cp tài liu tham kho | Không gii phóng sau khi chuyn thành công |

Hu hết các li tham chiếu đều đến t vic vi phm mt trong các quy tc này.

## 9.26 Chủ sở hữu trường đúng tối thiểu

Đây là mt đối tượng nh s hu mt trường đối tượng Python.```c
typedef struct {
    PyObject_HEAD
    PyObject *value;
} BoxObject;
```Khi to:```c
static int
Box_init(BoxObject *self, PyObject *args, PyObject *kwds)
{
    PyObject *value = NULL;

    if (!PyArg_ParseTuple(args, "O", &value)) {
        return -1;
    }

    Py_INCREF(value);
    self->value = value;

    return 0;
}
```Phân b:```c
static void
Box_dealloc(BoxObject *self)
{
    Py_XDECREF(self->value);
    Py_TYPE(self)->tp_free((PyObject *)self);
}
```Người nhn:```c
static PyObject *
Box_get_value(BoxObject *self, void *closure)
{
    Py_INCREF(self->value);
    return self->value;
}
```Người định cư:```c
static int
Box_set_value(BoxObject *self, PyObject *value, void *closure)
{
    if (value == NULL) {
        PyErr_SetString(PyExc_TypeError, "cannot delete value");
        return -1;
    }

    Py_INCREF(value);
    Py_XDECREF(self->value);
    self->value = value;

    return 0;
}
```Điu này cho thy mô hình s hu cơ bn:```text
own stored field
release stored field during destruction
return stored field as a new reference
replace field safely
```## 9.27 Mô hình tinh thần

Khi đọc mã CPython C, hãy hi nhng câu hi này cho mi`PyObject *`:

```text
Who owns this reference?
Was this returned as a new reference or borrowed reference?
Can this pointer be NULL?
What happens on the error path?
Does this container steal the reference?
Does this field need to INCREF when assigned?
Does this deallocator DECREF everything it owns?
Can a DECREF run arbitrary Python code through finalizers?
```Câu hi cui cùng tht tế nh. Gim tham chiếu có th phá hy mt đối tượng. Vic phá hy mt đối tượng có th gi các b hoàn thin. Trình hoàn thin có th chy mã Python. Mã Python có th thay đổi trng thái toàn cu. Vì thế,`Py_DECREF`có th có tác dng ph ln.

##9.28 Tóm tắt

Tính tham chiếu là cơ chế tn ti chính ca CPython. Mi đối tượng thông thường ghi li s lượng tham chiếu mnh tr đến nó.`Py_INCREF`giành được quyn s hu.`Py_DECREF`gii phóng quyn s hu. Khi s đếm đạt đến 0, CPython s phá hy đối tượng thông qua b gii phóng dành riêng cho loi ca nó.

Phn khó khăn không phi là b đếm. Phn khó khăn là k lut s hu. Mã m rng C phi phân bit các tham chiếu mi, tham chiếu mượn, tham chiếu b đánh cp, tham chiếu vô giá tr, tham chiếu tm thi, tham chiếu được lưu tr và tham chiếu được tr v.

Vic đếm tham chiếu gii thích phn ln hành vi ca CPython: hy b kp thi, dn dp xác định trong nhiu trường hp, quy tc mô-đun m rng, quyn s hu vùng cha và nhu cu v mt trình thu gom rác tun hoàn riêng bit.