12. Bố cục đối tượng và loại slot

CPython đại diện cho mọi giá trị thời gian chạy dưới dạng một đối tượng. Mỗi đối tượng có một bố cục bộ nhớ và loại của mỗi đối tượng mô tả cách diễn giải bộ nhớ đó.

Bố cục đối tượng trả lời:text What fields exist inside this object? Where are the references to other Python objects? How large is one instance? Does the object have variable-sized trailing storage? Does the object participate in cyclic garbage collection? Các loại slot trả lời:```text How is this object called? How is it deallocated? How does attribute lookup work? How does indexing work? How does addition work? How does iteration work? How is it represented as text?


## 12.1 Bộ nhớ đối tượng bắt đầu bằng tiêu đề

Mi đối tượng CPython bình thường đều bt đầu bng tiêu đề đối tượng.

V mt khái nim:```c
typedef struct {
    Py_ssize_t ob_refcnt;
    PyTypeObject *ob_type;
} PyObject;
```Điu này mang li cho mi đối tượng hai trường cơ bn:

| Lĩnh vc | Ý nghĩa |
| ----------- | ---------------------------- |
|`ob_refcnt`| S lượng tham kho |
|`ob_type`| Con tr ti loi đối tượng |

Mt đối tượng c th đặt các trường riêng ca nó sau tiêu đề này.

Hình dng ví d:```text
PyLongObject
    PyObject header
    integer-specific fields

PyListObject
    PyObject / PyVarObject header
    list-specific fields

PyFunctionObject
    PyObject header
    function-specific fields
```Vì mi đối tượng đều bt đầu bng cùng mt tiêu đề nên mã CPython chung có th thao tác vi các đối tượng không xác định thông qua`PyObject *`.

## 12.2 Bố cục đối tượng có kích thước cố định

Mt đối tượng có kích thước c định có cùng kích thước cu trúc C cho mi phiên bn.

Ví d:```c
typedef struct {
    PyObject_HEAD
    double value;
} FloatLikeObject;
```Hình dng b nh:```text
+--------------------+
| ob_refcnt          |
+--------------------+
| ob_type            |
+--------------------+
| value              |
+--------------------+
```Tt c các phiên bn thuc loi này có cùng kích thước.

Ví d v các cu trúc đối tượng có kích thước c định:```text
float
function
module
cell
method
weakref
many iterator objects
many descriptor objects
```Kích thước c định không có nghĩa là đối tượng không có tham chiếu đến b nh ngoài. Mt đối tượng hàm có cu trúc có kích thước c định, nhưng nó tr đến mt đối tượng mã, t đin toàn cc, b d liu mc định, b d liu đóng, chú thích và các đối tượng khác.

## 12.3 Bố cục đối tượng có kích thước thay đổi

Mt đối tượng có kích thước thay đổi s m rng tiêu đề chung bng trường kích thước.

V mt khái nim:```c
typedef struct {
    PyObject ob_base;
    Py_ssize_t ob_size;
} PyVarObject;
```Các loi tin ích m rng s dng:```c
typedef struct {
    PyObject_VAR_HEAD
    PyObject *items[1];
} ArrayLikeObject;
```Hình dng b nh:```text
+--------------------+
| ob_refcnt          |
+--------------------+
| ob_type            |
+--------------------+
| ob_size            |
+--------------------+
| variable payload   |
+--------------------+

ob_sizecó ý nghĩa đặc trưng cho từng loại.

Loại Ý nghĩa của trường kích thước
tuple Số phần tử
bytes Số byte
int Số và dấu của chữ số bên trong
loại biến tùy chỉnh Được xác định bởi việc thực hiện kiểu

12.4 Lưu trữ nội tuyến so với lưu trữ gián tiếp

Các giá trị Python có kích thước thay đổi có thể lưu trữ dữ liệu nội tuyến hoặc gián tiếp.

Một bộ lưu trữ các tham chiếu mục nội tuyến trong cùng một phân bổ:text tuple object header size = 3 item[0] ---> object A item[1] ---> object B item[2] ---> object C Một danh sách lưu trữ một con trỏ tới một mảng mục riêng biệt:```text list object header size = 3 ob_item ----+ allocated | v [ptr A][ptr B][ptr C][spare...]


Mt b d liu không th thay đổi kích thước sau khi phân b, do đó vic lưu tr ni tuyến s hiu qu.

Mt danh sách phi phát trin và thu nh li, do đó, nó gi các phn t trong mt mng riêng bit có th được phân b li mà không cn di chuyn chính đối tượng danh sách.

## 12.5 Kiểu đối tượng Mô tả bố cục cá thể

Mi đối tượng tr đến mt đối tượng kiu.

Đối tượng loi lưu tr siêu d liu b cc, chng hn như:```text
tp_basicsize
tp_itemsize
tp_dictoffset
tp_weaklistoffset
tp_flags
```Các trường quan trng:

| Lĩnh vc | Ý nghĩa |
| ------------------- | ------------------------------------- |
|`tp_basicsize`| Kích thước c định ca mt phiên bn |
|`tp_itemsize`| Kích thước ca mi mc  cui biến |
|`tp_dictoffset`| Ví d bù tr`__dict__`, nếu có |
|`tp_weaklistoffset`| Bù tr danh sách yếu, nếu được h tr |
|`tp_flags`| Gõ c mô t kh năng |

Đối vi loi có kích thước c định:```text
tp_basicsize = sizeof(MyObject)
tp_itemsize = 0
```Đối vi loi có kích thước thay đổi:```text
tp_basicsize = fixed header and fields
tp_itemsize = size of one trailing element
```Phân b sau đó tính toán:```text
total bytes = tp_basicsize + n * tp_itemsize
```Đây là cách CPython phân b mt b độ dài`n`trong mt khi b nh.

## 12.6 Kiểu đối tượng Mô tả hành vi

Mt đối tượng kiu cũng lưu tr hành vi.

Mt cái nhìn đơn gin hóa:```text
PyTypeObject
    name
    size fields
    base type
    method table
    member table
    getset table
    deallocator
    repr function
    call function
    attribute functions
    numeric slots
    sequence slots
    mapping slots
    iterator slots
```Khi Python đánh giá:```python
x + y
```CPython gi qua các khe loi.

Khi Python đánh giá:```python
x[i]
```CPython s dng các khe trình t hoc ánh x.

Khi Python đánh giá:```python
x()
```CPython s dng khe cuc gi.

Đối tượng kiu va là b mô t b cc va là bng điu phi.

## 12.7 Các loại slot chính`PyTypeObject`chứa nhiều trường. Các loại quan trọng là:

| Th loi slot | Mc đích |
| -------------------- | -------------------------------------------- |
| V trí vòng đời | phân b, khi to, phân b |
| Khe đại din |`repr`, `str`|
| Khe thuc tính | nhn, thiết lp, hành vi mô t |
| Khe gi | cú pháp gi hàm |
| Khe s | phép toán s hc và bit |
| Khe trình t | độ dài, lp ch mc, ngăn chn, ni |
| V trí bn đồ | tra cu và gán kiu t đin |
| Khe lp | giao thc lp |
| Khe đệm | tiếp xúc vi b nh thô |
| Khe GC | truyn ti và thanh toán bù tr |
| V trí phân lp | kế tha và hành vi MRO |

Mi danh mc ánh x cú pháp hoc hành vi thi gian chy ca Python ti các con tr hàm C.

## 12.8 Vị trí vòng đời

Các khe vòng đời kim soát vic to và hy.

Các slot quan trng:```text
tp_new
tp_init
tp_alloc
tp_dealloc
tp_free
```Đường dn sáng to đin hình:```text
call class
    tp_new allocates or returns object
    tp_init initializes object
    return object
```Ví d:```python
obj = MyClass(1, 2)
```V mt khái nim:```text
MyClass.__call__
    MyClass.__new__
    MyClass.__init__
``` cp độ C, điu này chy qua các khe loi.

Đối vi các đối tượng bt biến,`tp_new`thường xây dng giá tr đầy đủ vì đối tượng không th sa đổi sau khi to.

Đối vi các đối tượng có th thay đổi,`tp_init`có th đin hoc đặt li các trường sau khi phân b.

## 12.9 Khe phân bổ`tp_dealloc`phá hủy một đối tượng có số tham chiếu đạt tới 0.

Mt công c gii quyết đơn gin:```c
static void
Box_dealloc(BoxObject *self)
{
    Py_XDECREF(self->value);
    Py_TYPE(self)->tp_free((PyObject *)self);
}
```B gii phóng phi gii phóng mi tham chiếu Python thuc s hu ca đối tượng.

Đối vi các loi nhn biết GC, b gii phóng cũng phi hy theo dõi đối tượng trước khi ngt tham chiếu:```c
static void
Box_dealloc(BoxObject *self)
{
    PyObject_GC_UnTrack(self);
    Py_CLEAR(self->value);
    Py_TYPE(self)->tp_free((PyObject *)self);
}
```Mt người gii quyết phi được viết mt cách phòng th.`Py_DECREF`Và`Py_CLEAR`có th thc thi mã Python tùy ý mt cách gián tiếp thông qua các b hoàn thin.

## 12.10 Khe biểu diễn

H tr khe biu din`repr()`Và`str()`.

Các slot quan trng:```text
tp_repr
tp_str
```Mã Python:```python
repr(obj)
str(obj)
```bn đồ để gõ hành vi.

Bn phác tho trin khai kiu ví d:```c
static PyObject *
Counter_repr(CounterObject *self)
{
    return PyUnicode_FromFormat("Counter(%ld)", self->value);
}
```Sau đó:```python
repr(counter)
```có th sn xut:```text
Counter(10)
```Nếu như`tp_str`vng mt, CPython có th rơi tr li`tp_repr`hoc hành vi định dng đối tượng chung tùy thuc vào loi.

## 12.11 Khe truy cập thuộc tính

Truy cp thuc tính là mt trong nhng đường dn quan trng nht ca CPython.

Các v trí liên quan:```text
tp_getattro
tp_setattro
tp_getattr
tp_setattr
```Các loi hin đại thường s dng`tp_getattro`Và`tp_setattro`.

Mã Python:```python
obj.name
obj.name = value
del obj.name
```chy qua máy móc thuc tính.

Đối vi các đối tượng thông thường, vic tra cu thuc tính chung s x lý:```text
data descriptors
instance dictionary
non-data descriptors
class attributes
base classes
__getattr__
```Loi tùy chnh có th ghi đè hành vi này bng cách cung cp các v trí thuc tính tùy chnh.

## 12.12 Khe mô tả

B mô t thc hin hành vi ràng buc.

Mt kiu mô t có th định nghĩa:```text
tp_descr_get
tp_descr_set
```Tương đương cp độ Python:```python
__get__
__set__
__delete__
```Chc năng là mô t. Khi mt hàm được lưu tr trên mt lp và được truy cp thông qua mt th hin, logic mô t s to ra mt phương thc b ràng buc.```python
class Counter:
    def inc(self):
        return 1

c = Counter()
m = c.inc
```V mt khái nim:```text
look up inc on Counter
find function object
function descriptor binds self = c
return bound method
```B mô t trin khai các phương thc, thuc tính, phương thc lp, phương thc tĩnh, v trí và nhiu thuc tính tích hp.

## 12.13 Khe gọi

Khe cuc gi h tr cú pháp gi hàm.

V trí có liên quan:```text
tp_call
```Mã Python:```python
obj(a, b, c)
```yêu cu loi đối tượng có th gi được.

Hàm, lp, phương thc, hàm dng sn và đối tượng vi`__call__`đều tham gia vào giao thc này.

Đối vi lp do người dùng định nghĩa:```python
class F:
    def __call__(self, x):
        return x + 1

f = F()
print(f(10))
``` cp độ loi, máy móc lp đảm bo các phiên bn có`__call__`hot động như các đối tượng có th gi được.

## 12.14 Khe số

Các khe s x lý các phép toán s hc và bitwise.

H sng trong mt`PyNumberMethods`bàn.

Các khe khái nim ph biến:```text
nb_add
nb_subtract
nb_multiply
nb_remainder
nb_power
nb_negative
nb_positive
nb_absolute
nb_bool
nb_invert
nb_lshift
nb_rshift
nb_and
nb_xor
nb_or
nb_int
nb_float
nb_index
```Cú pháp Python:```python
a + b
a - b
a * b
-a
bool(a)
a & b
a << b
```s dng máy móc giao thc s.

Đối vi các lp do người dùng định nghĩa, các phương thc đặc bit như`__add__`, `__bool__`, Và`__index__`được kết ni vi các khe này.

## 12.15 Công văn hoạt động nhị phân

Các phép toán nh phân cn được gi đi cn thn vì hai toán hng có hai loi.

Vì:```python
a + b
```CPython có th xem xét:```text
left operand type
right operand type
subclass relationships
left slot
right reflected slot
NotImplemented result
```Các phương thc cp độ Python:```python
__add__
__radd__
__iadd__
```bn đồ ti máy móc hot động nh phân ni b.

Mt loi có th tr li`NotImplemented`để cho toán hng khác tham gia.

Ví d:```python
class A:
    def __add__(self, other):
        return NotImplemented

class B:
    def __radd__(self, other):
        return "handled by B"

print(A() + B())
```Hành vi điu phi này là mt phn ca mô hình d liu ca Python và được trin khai thông qua các khe kiu.

## 12.16 Khe trình tự

Các khe trình t tn ti trong mt`PySequenceMethods`bàn.

Các khe khái nim ph biến:```text
sq_length
sq_concat
sq_repeat
sq_item
sq_ass_item
sq_contains
sq_inplace_concat
sq_inplace_repeat
```Cú pháp Python:```python
len(x)
x[i]
x[i] = value
item in x
x + y
x * n
```có th s dng các khe trình t.

Danh sách, b d liu, chui, byte và phm vi đều th hin hành vi trình t, mc dù b cc bên trong ca chúng khác nhau.

## 12.17 Khe bản đồ

Các v trí bn đồ tn ti trong mt`PyMappingMethods`bàn.

Các khe khái nim ph biến:```text
mp_length
mp_subscript
mp_ass_subscript
```Cú pháp Python:```python
len(x)
x[key]
x[key] = value
del x[key]
```có th s dng các khe bn đồ.

T đin là loi ánh x chính.

Mt đối tượng do người dùng định nghĩa thc hin`__getitem__`, `__setitem__`, Và`__len__`có th tham gia vào hành vi ging như lp bn đồ thông qua tích hp khe loi.

## 12.18 Tra cứu trình tự và ánh xạ

Cú pháp tương t có th có nghĩa là truy cp trình t hoc ánh x:```python
x[i]
```Đối vi mt danh sách,`i`là mt ch mc.

Đối vi mt lnh,`i`là mt chiếc chìa khóa.

Loi quyết định cách din gii hot động.

V mt khái nim:```text
list.__getitem__(index)
    index must be integer-like

dict.__getitem__(key)
    key may be any hashable object
``` cp độ C, CPython gi đi da trên v trí trình t và ánh x ca loi.

## 12.19 Khe lặp vòng lặp

Lp li s dng h tr giao thc cp loi.

Các v trí liên quan:```text
tp_iter
tp_iternext
```Mã Python:```python
for item in obj:
    ...
```đại khái có nghĩa là:```text
iterator = iter(obj)
while true:
    try:
        item = next(iterator)
    except StopIteration:
        break
``` cp độ C:```text
tp_iter
    returns iterator object

tp_iternext
    returns next item or signals StopIteration
```Mt iterator t tr v chính nó t`tp_iter`.

Mt vùng cha tr v mt đối tượng lp riêng bit.

## 12.20 Khe đệm

Giao thc b đệm hin th b nh thô cho các đối tượng khác mà không cn sao chép.

Khu vc v trí có liên quan:```text
tp_as_buffer
```Các đối tượng như`bytes`, `bytearray`, `memoryview`, mng và các kiu m rng s có th tham gia.

Giao thc b đệm quan trng đối vi:```text
zero-copy I/O
binary parsing
NumPy interop
memoryview
file and socket operations
serialization
```Trình xut b đệm phi gi cho b nh hp l trong khi người tiêu dùng gi chế độ xem.

Điu này làm cho các khe đệm tr thành mt phn ca c mô hình đối tượng và mô hình thi gian tn ti ca b nh.

## 12.21 Khe thu gom rác

Các loi vùng cha nhn biết GC cn h tr truyn ti và xóa.

Các v trí liên quan:```text
tp_traverse
tp_clear

tp_traversecác báo cáo chứa các tham chiếu Python tới bộ sưu tập.```c static int Box_traverse(BoxObject *self, visitproc visit, void *arg) { Py_VISIT(self->value); return 0; }


`tp_clear`ngắt chứa các tham chiếu trong quá trình thu thập theo chu kỳ.```c
static int
Box_clear(BoxObject *self)
{
    Py_CLEAR(self->value);
    return 0;
}
```Nếu một loại  thể tham gia vào các chu trình  không thực hiện đúng các chu trình này,   thể  rỉ các chu trình không thể truy cập được.

## 12.22 Bảng thành viên

Một số trường mở rộng C  thể được hiển thị thông qua các định nghĩa thành viên.

Mẫu khái niệm:```c
static PyMemberDef Point_members[] = {
    {"x", T_LONG, offsetof(PointObject, x), 0, "x coordinate"},
    {"y", T_LONG, offsetof(PointObject, y), 0, "y coordinate"},
    {NULL}
};
```Đối tượng loại trỏ đến bảng này.```c
.tp_members = Point_members
```Điều này cho phép CPython hiển thị các trường cấu trúc C dưới dạng thuộc tính Python.

Bảng thành viên rất hữu ích cho các trường C đơn giản. Các thuộc tính phức tạp hơn thường sử dụng bộ  tả getset.

## 12.23 Bảng Getset

Bảng Getset hiển thị các thuộc tính được tính toán.

Mẫu khái niệm:```c
static PyObject *
Point_get_norm(PointObject *self, void *closure)
{
    double norm = sqrt(self->x * self->x + self->y * self->y);
    return PyFloat_FromDouble(norm);
}

static PyGetSetDef Point_getset[] = {
    {"norm", (getter)Point_get_norm, NULL, "vector norm", NULL},
    {NULL}
};
```Đối tượng loại trỏ đến bảng getset:```c
.tp_getset = Point_getset
```Mục getset hoạt động giống như một bộ  tả.

 Python:```python
p.norm
```gọi getter.

## 12.24 Bảng phương thức

Các phương thức mở rộng C được hiển thị thông qua các bảng phương thức.

Mẫu khái niệm:```c
static PyObject *
Counter_inc(CounterObject *self, PyObject *Py_UNUSED(ignored))
{
    self->value += 1;
    return PyLong_FromLong(self->value);
}

static PyMethodDef Counter_methods[] = {
    {"inc", (PyCFunction)Counter_inc, METH_NOARGS, "increment counter"},
    {NULL}
};
```Đối tượng kiểu trỏ đến bảng phương thức:```c
.tp_methods = Counter_methods
``` Python:```python
counter.inc()
```sử dụng bộ  tả  máy gọi phương thức để gọi hàm C.

## 12.25 Các loại heap và các loại tĩnh

CPython  loại tĩnh  loại heap.

Các kiểu tĩnh được định nghĩa  cấu trúc toàn cầu C. Nhiều kiểu tích hợp trong lịch sử sử dụng các đối tượng kiểu tĩnh.

Các loại heap được phân bổ động trong thời gian chạy. Các lớp Python do người dùng định nghĩa  các loại heap.

So sánh:

| Loại loại | Phân bổ | Sử dụng điển hình |
| ----------- | ------------------ | --------------------------------------------- |
| Loại tĩnh | Lưu trữ tĩnh C | Các loại tích hợp  được xác định bằng tiện ích mở rộng |
| Loại đống | Phân bổ thời gian chạy | Lớp Python, nhiều kiểu mở rộng hiện đại |

Các loại heap linh hoạt hơn. Chúng hỗ trợ hành vi lớp thông thường như thuộc tính động, siêu dữ liệu phân lớp  vòng đời được quản  theo thời gian chạy.

 mở rộng hiện đại thường thích các loại heap thông qua các khe định nghĩa -đun `PyType_FromSpec`.

## 12,26`PyType_FromSpec`

`PyType_FromSpec`tạo một đối tượng kiểu từ một đặc tả khai báo.

Khái niệm phác thảo:```c
static PyType_Slot Counter_slots[] = {
    {Py_tp_dealloc, Counter_dealloc},
    {Py_tp_methods, Counter_methods},
    {0, NULL}
};

static PyType_Spec Counter_spec = {
    .name = "example.Counter",
    .basicsize = sizeof(CounterObject),
    .itemsize = 0,
    .flags = Py_TPFLAGS_DEFAULT,
    .slots = Counter_slots,
};
```Sau đó:```c
PyObject *type = PyType_FromSpec(&Counter_spec);
```Phong cách này tránh việc khởi tạo trực tiếp một số lượng lớn`PyTypeObject`struct  hoạt động tốt hơn với nội bộ CPython đang phát triển.

## 12.27 Kế thừa vị trí

Các lớp con kế thừa hành vi từ các lớp  sở trừ khi chúng ghi đè lên .```python
class A:
    def __len__(self):
        return 10

class B(A):
    pass

print(len(B()))

Bkế thừa hành vi độ dài từA.

Ở cấp độ C, tính sẵn sàng của loại sẽ lấp đầy các vị trí được kế thừa và tính toán siêu dữ liệu về bố cục loại và độ phân giải phương thức cuối cùng.

Kế thừa vị trí phải tôn trọng:```text base class layout method resolution order descriptor behavior special method lookup type flags GC support memory offsets


## 12.28 Tra cứu phương pháp đặc biệt

Tra cu phương pháp đặc bit thường b qua vic tra cu phiên bn thông thường.

Ví d:```python
class X:
    pass

x = X()
x.__len__ = lambda: 3

len(x)
```Điu này vn làm tăng`TypeError`bi vì`len(x)`tìm kiếm hành vi độ dài trên loi ch không phi trong t đin mu.

Chính xác:```python
class X:
    def __len__(self):
        return 3

x = X()
print(len(x))
```Quy tc này cho phép CPython ti ưu hóa các hot động ca giao thc và duy trì hành vi nht quán cho cú pháp tích hp.

## 12.29 Xung đột về bố cục

Nhiu kế tha có th to ra xung đột v b cc.

Nếu hai lp cơ s yêu cu b cc phiên bn cp C không tương thích thì CPython có th t chi lp đó.

Hình dng ví d:```text
BaseA requires C layout A
BaseB requires C layout B
Derived(BaseA, BaseB)
    cannot combine both layouts safely
```Các lp Python thun túy thường linh hot vì trng thái phiên bn ca chúng da trên t đin hoc da trên v trí.

Các loi tin ích m rng C có yêu cu b cc cht ch hơn.

Đây là mt lý do khiến thiết kế kiu m rng phi thn trng v tính kế tha tr khi hành vi phân lp con là cn thiết mt cách rõ ràng.

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

S dng mô hình này khi đọc mã loi:```text
object memory stores state
type object describes layout and behavior
slots map Python operations to C functions
protocols are implemented through slot tables
attribute lookup uses descriptors and dictionaries
numeric, sequence, and mapping syntax dispatch through specialized slots
GC-aware objects must expose references through traversal slots
deallocation must release owned references and free memory
```Biu thc Python thường là mt đường dn xuyên qua các khe kiu.```python
result = obj[key] + other
```V mt khái nim:```text
load obj
dispatch subscription through mapping or sequence slot
load other
dispatch addition through number slots
store result
```## 12.31 Tóm tắt

B cc đối tượng xác định hình dng b nh ca đối tượng CPython. Các khe loi xác định nhng hot động mà đối tượng h tr.`PyObject`Và`PyVarObject`cung cp các tiêu đề chung. Cu trúc c th thêm các trường dành riêng cho loi.`PyTypeObject`ghi li kích thước, độ lch, c, móc vòng đời, hành vi thuc tính, v trí giao thc, bng phương thc, bng thành viên, bng getset và h tr thu gom rác.

Thiết kế này cho phép CPython kết hp mt biu din đối tượng thng nht vi các trin khai có tính chuyên môn cao cho các loi tin ích m rng và tích hp sn.