3. Mô hình dữ liệu

3.1. Đối tượng, giá trị và loại

Objects là sự trừu tượng hóa dữ liệu của Python. Tất cả dữ liệu trong chương trình Python được biểu diễn bằng các đối tượng hoặc bằng quan hệ giữa các đối tượng. Ngay cả mã cũng được đại diện bởi các đối tượng.

Mỗi đối tượng đều có một danh tính, một loại và một giá trị. identity của một đối tượng không bao giờ thay đổi sau khi nó được tạo; bạn có thể coi nó như địa chỉ của đối tượng trong bộ nhớ. Toán tử is so sánh danh tính của hai đối tượng; hàm id() trả về một số nguyên biểu thị danh tính của nó.

Đối với CPython, id(x) là địa chỉ bộ nhớ nơi lưu trữ x.

Kiểu của một đối tượng xác định các hoạt động mà đối tượng đó hỗ trợ (ví dụ: "nó có độ dài không?") và cũng xác định các giá trị có thể có cho các đối tượng thuộc loại đó. Hàm type() trả về kiểu của một đối tượng (chính là một đối tượng). Giống như danh tính của nó, type của một đối tượng cũng không thể thay đổi được. [1]

Zz000zz của một số đối tượng có thể thay đổi. Các đối tượng có giá trị có thể thay đổi được gọi là mutable; các đối tượng có giá trị không thể thay đổi khi chúng được tạo được gọi là immutable. (Giá trị của một đối tượng vùng chứa bất biến chứa tham chiếu đến một đối tượng có thể thay đổi có thể thay đổi khi giá trị của đối tượng sau bị thay đổi; tuy nhiên, vùng chứa vẫn được coi là bất biến, vì tập hợp các đối tượng mà nó chứa không thể thay đổi. Vì vậy, tính bất biến không hoàn toàn giống như việc có một giá trị không thể thay đổi, nó tinh tế hơn.) Tính biến đổi của một đối tượng được xác định bởi loại của nó; ví dụ: số, chuỗi và bộ dữ liệu là bất biến, trong khi từ điển và danh sách có thể thay đổi.

Các đối tượng không bao giờ bị phá hủy một cách rõ ràng; tuy nhiên, khi không thể truy cập được, chúng có thể bị thu gom rác. Việc triển khai được phép trì hoãn việc thu thập rác hoặc bỏ qua nó hoàn toàn --- vấn đề là chất lượng triển khai cách triển khai việc thu gom rác, miễn là không có đối tượng nào được thu thập mà vẫn có thể truy cập được.

CPython hiện sử dụng sơ đồ đếm tham chiếu với khả năng phát hiện rác liên kết theo chu kỳ bị trì hoãn (tùy chọn), thu thập hầu hết các đối tượng ngay khi chúng không thể truy cập được, nhưng không đảm bảo thu thập rác có chứa tham chiếu vòng tròn. Xem tài liệu của mô-đun gc để biết thông tin về cách kiểm soát việc thu thập rác tuần hoàn. Các triển khai khác hoạt động khác và CPython có thể thay đổi. Đừng phụ thuộc vào việc hoàn thiện ngay lập tức các đối tượng khi chúng không thể truy cập được (vì vậy bạn phải luôn đóng các tệp một cách rõ ràng).

Lưu ý rằng việc sử dụng các phương tiện theo dõi hoặc gỡ lỗi của quá trình triển khai có thể giữ cho các đối tượng vẫn tồn tại mà thông thường có thể thu thập được. Cũng lưu ý rằng việc bắt ngoại lệ bằng câu lệnh try...except có thể giữ cho các đối tượng vẫn tồn tại.

Một số đối tượng chứa các tham chiếu đến các tài nguyên "bên ngoài" như các tệp hoặc cửa sổ đang mở. Điều này được hiểu rằng các tài nguyên này được giải phóng khi đối tượng được thu gom rác, nhưng vì việc thu gom rác không đảm bảo sẽ xảy ra nên các đối tượng đó cũng cung cấp một cách rõ ràng để giải phóng tài nguyên bên ngoài, thường là phương thức close(). Các chương trình được khuyến khích đóng các đối tượng như vậy một cách rõ ràng. Câu lệnh try...:keyword:finally và câu lệnh with cung cấp những cách thuận tiện để thực hiện việc này.

Một số đối tượng chứa tham chiếu đến các đối tượng khác; chúng được gọi là containers. Ví dụ về các thùng chứa là bộ dữ liệu, danh sách và từ điển. Các tham chiếu là một phần giá trị của vùng chứa. Trong hầu hết các trường hợp, khi chúng ta nói về giá trị của vùng chứa, chúng ta ám chỉ các giá trị chứ không phải danh tính của các đối tượng được chứa; tuy nhiên, khi chúng ta nói về khả năng thay đổi của một vùng chứa, chỉ có danh tính của các đối tượng được chứa ngay lập tức được ngụ ý. Vì vậy, nếu một vùng chứa bất biến (như bộ dữ liệu) chứa tham chiếu đến một đối tượng có thể thay đổi, thì giá trị của nó sẽ thay đổi nếu đối tượng có thể thay đổi đó bị thay đổi.

Các loại ảnh hưởng đến hầu hết các khía cạnh của hành vi đối tượng. Ngay cả tầm quan trọng của nhận dạng đối tượng cũng bị ảnh hưởng theo một nghĩa nào đó: đối với các loại không thay đổi, các hoạt động tính toán các giá trị mới thực sự có thể trả về một tham chiếu đến bất kỳ đối tượng hiện có nào có cùng loại và giá trị, trong khi đối với các đối tượng có thể thay đổi thì điều này không được phép. Ví dụ: sau a = 1; b = 1, ab có thể hoặc không thể tham chiếu đến cùng một đối tượng có giá trị một, tùy thuộc vào cách triển khai. Điều này là do int là loại không thể thay đổi nên tham chiếu đến 1 có thể được sử dụng lại. Hành vi này phụ thuộc vào việc triển khai được sử dụng, do đó không nên dựa vào, nhưng là điều cần lưu ý khi sử dụng các bài kiểm tra nhận dạng đối tượng. Tuy nhiên, sau c = []; d = [], cd được đảm bảo đề cập đến hai danh sách trống khác nhau, duy nhất, mới được tạo. (Lưu ý rằng e = f = [] gán đối tượng same cho cả ef.)

3.2. Hệ thống phân cấp loại tiêu chuẩn

Dưới đây là danh sách các kiểu được tích hợp trong Python. Các mô-đun mở rộng (được viết bằng C, Java hoặc các ngôn ngữ khác, tùy thuộc vào cách triển khai) có thể xác định các loại bổ sung. Các phiên bản tương lai của Python có thể thêm các kiểu vào hệ thống phân cấp kiểu (ví dụ: số hữu tỷ, mảng số nguyên được lưu trữ hiệu quả, v.v.), mặc dù những bổ sung như vậy thường sẽ được cung cấp thông qua thư viện tiêu chuẩn.

Một số mô tả loại bên dưới có chứa đoạn liệt kê 'thuộc tính đặc biệt'. Đây là các thuộc tính cung cấp quyền truy cập vào việc triển khai và không nhằm mục đích sử dụng chung. Định nghĩa của họ có thể thay đổi trong tương lai.

3.2.1. không có

Loại này có một giá trị duy nhất. Có một đối tượng duy nhất có giá trị này. Đối tượng này được truy cập thông qua tên tích hợp None. Nó được sử dụng để biểu thị sự vắng mặt của một giá trị trong nhiều trường hợp, ví dụ: nó được trả về từ các hàm không trả về bất kỳ giá trị nào một cách rõ ràng. Giá trị thật của nó là sai.

3.2.2. Chưa thực hiện

Loại này có một giá trị duy nhất. Có một đối tượng duy nhất có giá trị này. Đối tượng này được truy cập thông qua tên tích hợp NotImplemented. Các phương pháp số và phương pháp so sánh phong phú sẽ trả về giá trị này nếu chúng không triển khai thao tác cho các toán hạng được cung cấp. (Sau đó, trình thông dịch sẽ thử thao tác được phản ánh hoặc một số thao tác dự phòng khác, tùy thuộc vào toán tử.) Không nên đánh giá nó trong ngữ cảnh boolean.

Xem Thực hiện các phép tính số học để biết thêm chi tiết.

Thay đổi trong phiên bản 3.9: Việc đánh giá NotImplemented trong ngữ cảnh boolean không được dùng nữa.

Thay đổi trong phiên bản 3.14: Việc đánh giá NotImplemented trong ngữ cảnh boolean hiện đưa ra TypeError. Trước đây nó được đánh giá là True và phát ra DeprecationWarning kể từ Python 3.9.

3.2.3. dấu ba chấm

Loại này có một giá trị duy nhất. Có một đối tượng duy nhất có giá trị này. Đối tượng này được truy cập thông qua ... theo nghĩa đen hoặc tên cài sẵn Ellipsis. Giá trị chân lý của nó là đúng.

3.2.4. numbers.Number

Chúng được tạo bởi các ký tự số và được trả về dưới dạng kết quả bởi các toán tử số học và các hàm số học tích hợp sẵn. Đối tượng số là bất biến; một khi được tạo ra, giá trị của chúng không bao giờ thay đổi. Tất nhiên, số Python có liên quan chặt chẽ với các số toán học, nhưng chịu những hạn chế về biểu diễn số trong máy tính.

Biểu diễn chuỗi của các lớp số, được tính toán bởi __repr__()__str__(), có các thuộc tính sau:

  • Chúng là các ký tự số hợp lệ, khi được truyền cho hàm tạo của lớp, sẽ tạo ra một đối tượng có giá trị của số gốc.

  • Biểu diễn ở cơ số 10, khi có thể.

  • Các số 0 đứng đầu, có thể ngoại trừ một số 0 duy nhất trước dấu thập phân, không được hiển thị.

  • Các số 0 ở cuối, có thể ngoại trừ một số 0 duy nhất sau dấu thập phân, không được hiển thị.

  • Dấu chỉ được hiển thị khi số âm.

Python phân biệt giữa số nguyên, số dấu phẩy động và số phức:

3.2.4.1. numbers.Integral

Chúng đại diện cho các phần tử từ tập hợp toán học của các số nguyên (dương và âm).

Ghi chú

Các quy tắc biểu diễn số nguyên nhằm mục đích đưa ra cách giải thích có ý nghĩa nhất về các phép dịch và mặt nạ liên quan đến số nguyên âm.

Có hai loại số nguyên:

Số nguyên (int)

Chúng đại diện cho các số trong phạm vi không giới hạn, chỉ tùy thuộc vào bộ nhớ (ảo) có sẵn. Với mục đích của các phép toán dịch chuyển và mặt nạ, giả sử biểu diễn nhị phân và các số âm được biểu diễn dưới dạng biến thể của phần bù 2, tạo ảo giác về một chuỗi bit dấu vô hạn kéo dài sang trái.

Boolean (bool)

Chúng đại diện cho các giá trị thật Sai và Đúng. Hai đối tượng đại diện cho các giá trị FalseTrue là các đối tượng Boolean duy nhất. Loại Boolean là một loại con của loại số nguyên và các giá trị Boolean hoạt động giống như các giá trị 0 và 1 tương ứng trong hầu hết các ngữ cảnh, ngoại trừ khi được chuyển đổi thành một chuỗi, các chuỗi "False" hoặc "True" sẽ được trả về tương ứng.

3.2.4.2. numbers.Real (float)

Chúng đại diện cho các số dấu phẩy động có độ chính xác kép ở cấp độ máy. Bạn có thể tùy ý sử dụng kiến ​​trúc máy cơ bản (và cách triển khai C hoặc Java) đối với phạm vi được chấp nhận và cách xử lý tràn. Python không hỗ trợ các số dấu phẩy động có độ chính xác đơn; mức tiết kiệm trong việc sử dụng bộ xử lý và bộ nhớ thường là lý do để sử dụng những thứ này bị giảm đi do chi phí sử dụng các đối tượng trong Python, do đó không có lý do gì để làm phức tạp ngôn ngữ với hai loại số dấu phẩy động.

3.2.4.3. numbers.Complex (complex)

Chúng biểu diễn các số phức dưới dạng một cặp số dấu phẩy động có độ chính xác kép ở cấp độ máy. Những cảnh báo tương tự cũng được áp dụng như đối với các số có dấu phẩy động. Phần thực và phần ảo của số phức z có thể được truy xuất thông qua các thuộc tính chỉ đọc z.realz.imag.

3.2.5. trình tự

Chúng đại diện cho các tập hợp có thứ tự hữu hạn được lập chỉ mục bởi các số không âm. Hàm tích hợp len() trả về số mục của một chuỗi. Khi độ dài của chuỗi là n, tập chỉ mục chứa các số 0, 1, ..., n-1. Mục i của dãy a được a[i] chọn. Một số trình tự, bao gồm các trình tự dựng sẵn, giải thích các chỉ số dưới âm bằng cách thêm độ dài trình tự. Ví dụ: a[-2] bằng a[n-2], mục thứ hai đến mục cuối cùng của chuỗi a có độ dài n.

Giá trị kết quả phải là số nguyên không âm nhỏ hơn số mục trong chuỗi. Nếu không, IndexError sẽ được nâng lên.

Trình tự cũng hỗ trợ cắt: a[start:stop] chọn tất cả các mục có chỉ mục k sao cho start <= k < stop. Khi được sử dụng làm biểu thức, lát cắt là một chuỗi cùng loại. Nhận xét ở trên về chỉ số dưới âm cũng áp dụng cho các vị trí lát cắt âm. Lưu ý rằng không có lỗi nào xảy ra nếu vị trí lát cắt nhỏ hơn 0 hoặc lớn hơn độ dài của chuỗi.

Nếu start bị thiếu hoặc None, việc cắt sẽ hoạt động như thể start bằng 0. Nếu stop bị thiếu hoặc None, việc cắt sẽ hoạt động như thể stop bằng độ dài của chuỗi.

Một số trình tự cũng hỗ trợ "cắt mở rộng" với tham số "bước" thứ ba: a[i:j:k] chọn tất cả các mục của a với chỉ mục x trong đó x = i + n*k, n >= 0i <= x < j.

Trình tự được phân biệt theo khả năng biến đổi của chúng:

3.2.5.1. Trình tự bất biến

Một đối tượng thuộc loại trình tự bất biến không thể thay đổi một khi nó được tạo. (Nếu đối tượng chứa các tham chiếu đến các đối tượng khác, các đối tượng khác này có thể thay đổi và có thể bị thay đổi; tuy nhiên, tập hợp các đối tượng được tham chiếu trực tiếp bởi một đối tượng bất biến không thể thay đổi.)

Các loại sau đây là trình tự bất biến:

Dây

Chuỗi (str) là một chuỗi các giá trị đại diện cho characters hoặc chính thức hơn là Unicode code points. Tất cả các điểm mã trong phạm vi 0 đến 0x10FFFF có thể được biểu diễn dưới dạng chuỗi.

Python không có loại character chuyên dụng. Thay vào đó, mọi điểm mã trong chuỗi được biểu diễn dưới dạng đối tượng chuỗi có độ dài 1.

Hàm tích hợp ord() chuyển đổi một điểm mã từ dạng chuỗi thành số nguyên trong phạm vi 0 đến 0x10FFFF; chr() chuyển đổi một số nguyên trong phạm vi 0 thành 0x10FFFF thành đối tượng chuỗi 1 có độ dài tương ứng. str.encode() có thể được sử dụng để chuyển đổi str thành bytes bằng cách sử dụng mã hóa văn bản nhất định và bytes.decode() có thể được sử dụng để đạt được điều ngược lại.

Bộ dữ liệu

Các mục của tuple là các đối tượng Python tùy ý. Các bộ gồm hai hoặc nhiều mục được hình thành bởi danh sách các biểu thức được phân tách bằng dấu phẩy. Một bộ gồm một mục ('singleton') có thể được tạo bằng cách gắn dấu phẩy vào một biểu thức (bản thân một biểu thức không tạo ra một bộ, vì phải sử dụng được dấu ngoặc đơn để nhóm các biểu thức). Một bộ trống có thể được hình thành bởi một cặp dấu ngoặc đơn trống.

Byte

Đối tượng bytes là một mảng bất biến. Các mục là byte 8 bit, được biểu thị bằng các số nguyên trong phạm vi 0 <= x < 256. Các ký tự byte (như b'abc') và hàm tạo bytes() tích hợp có thể được sử dụng để tạo các đối tượng byte. Ngoài ra, các đối tượng byte có thể được giải mã thành chuỗi thông qua phương thức decode().

3.2.5.2. Trình tự có thể thay đổi

Trình tự có thể thay đổi có thể được thay đổi sau khi chúng được tạo. Các ký hiệu đăng ký và cắt có thể được sử dụng làm mục tiêu của các câu lệnh gán và del (xóa).

Ghi chú

Mô-đun collectionsarray cung cấp các ví dụ bổ sung về các loại trình tự có thể thay đổi.

Hiện tại có hai loại trình tự có thể thay đổi nội tại:

Danh sách

Các mục của danh sách là các đối tượng Python tùy ý. Danh sách được hình thành bằng cách đặt danh sách các biểu thức được phân tách bằng dấu phẩy trong dấu ngoặc vuông. (Lưu ý rằng không cần có trường hợp đặc biệt nào để tạo danh sách có độ dài 0 hoặc 1.)

Mảng byte

Đối tượng bytearray là một mảng có thể thay đổi được. Chúng được tạo bởi hàm tạo bytearray() tích hợp sẵn. Ngoài việc có thể thay đổi (và do đó không thể băm), mảng byte còn cung cấp giao diện và chức năng tương tự như các đối tượng bytes bất biến.

3.2.6. Đặt loại

Chúng đại diện cho các tập hợp hữu hạn, không có thứ tự của các đối tượng duy nhất, bất biến. Như vậy, chúng không thể được lập chỉ mục bởi bất kỳ chỉ số dưới nào. Tuy nhiên, chúng có thể được lặp lại và hàm tích hợp len() trả về số lượng mục trong một bộ. Các cách sử dụng phổ biến cho các tập hợp là kiểm tra thành viên nhanh chóng, loại bỏ các bản sao khỏi một chuỗi và tính toán các phép toán như giao, hợp, sai phân và sai đối xứng.

Đối với các phần tử tập hợp, các quy tắc bất biến tương tự được áp dụng như đối với khóa từ điển. Lưu ý rằng các kiểu số tuân theo các quy tắc thông thường để so sánh số: nếu hai số so sánh bằng nhau (ví dụ: 11.0), thì chỉ một trong số chúng có thể được chứa trong một tập hợp.

Hiện tại có hai loại tập hợp nội tại:

bộ

Chúng đại diện cho một tập hợp có thể thay đổi. Chúng được tạo bởi hàm tạo set() tích hợp và có thể được sửa đổi sau đó bằng một số phương pháp, chẳng hạn như add().

Bộ đông lạnh

Chúng đại diện cho một tập hợp bất biến. Chúng được tạo bởi hàm tạo frozenset() tích hợp sẵn. Vì một tập hợp đông lạnh là bất biến và hashable nên nó có thể được sử dụng lại như một phần tử của tập hợp khác hoặc làm khóa từ điển.

3.2.7. Ánh xạ

Chúng đại diện cho các tập hợp hữu hạn các đối tượng được lập chỉ mục bởi các bộ chỉ mục tùy ý. Ký hiệu chỉ số dưới a[k] chọn mục được k lập chỉ mục từ ánh xạ a; cái này có thể được sử dụng trong các biểu thức và làm mục tiêu của các phép gán hoặc câu lệnh del. Hàm tích hợp len() trả về số lượng mục trong ánh xạ.

Hiện tại có một loại ánh xạ nội tại duy nhất:

3.2.7.1. Từ điển

Chúng đại diện cho các tập hợp hữu hạn các đối tượng được lập chỉ mục bởi các giá trị gần như tùy ý. Các loại giá trị duy nhất không được chấp nhận làm khóa là các giá trị chứa danh sách hoặc từ điển hoặc các loại có thể thay đổi khác được so sánh theo giá trị thay vì theo danh tính đối tượng, lý do là việc triển khai từ điển hiệu quả yêu cầu giá trị băm của khóa không đổi. Các kiểu số được sử dụng cho khóa tuân theo các quy tắc thông thường để so sánh số: nếu hai số so sánh bằng nhau (ví dụ: 11.0) thì chúng có thể được sử dụng thay thế cho nhau để lập chỉ mục cho cùng một mục từ điển.

Từ điển giữ nguyên thứ tự chèn, nghĩa là các khóa sẽ được tạo theo cùng thứ tự mà chúng được thêm tuần tự vào từ điển. Việc thay thế khóa hiện có không làm thay đổi thứ tự, tuy nhiên, việc xóa khóa và chèn lại sẽ thêm khóa đó vào cuối thay vì giữ nguyên vị trí cũ.

Từ điển có thể thay đổi được; chúng có thể được tạo bằng ký hiệu {} (xem phần Hiển thị từ điển).

Các mô-đun mở rộng dbm.ndbmdbm.gnu cung cấp các ví dụ bổ sung về các loại ánh xạ, cũng như mô-đun collections.

Thay đổi trong phiên bản 3.7: Từ điển không giữ nguyên thứ tự chèn trong các phiên bản Python trước 3.6. Trong CPython 3.6, thứ tự chèn vẫn được giữ nguyên, nhưng vào thời điểm đó nó được coi là một chi tiết triển khai hơn là một sự đảm bảo về ngôn ngữ.

3.2.8. Các loại có thể gọi được

Đây là những loại mà thao tác gọi hàm có thể được áp dụng (xem phần Cuộc gọi):

3.2.8.1. Các hàm do người dùng xác định

Đối tượng hàm do người dùng định nghĩa được tạo bởi định nghĩa hàm (xem phần định nghĩa hàm). Nó phải được gọi với một danh sách đối số chứa cùng số mục như danh sách tham số chính thức của hàm.

3.2.8.1.1. Thuộc tính chỉ đọc đặc biệt

Thuộc tính

Ý nghĩa

function.__builtins__

Tham chiếu đến dictionary chứa không gian tên nội trang của hàm.

Added in version 3.10.

function.__globals__

Tham chiếu đến dictionary chứa global variables của hàm -- vùng tên chung của mô-đun mà hàm được xác định.

function.__closure__

None hoặc tuple ô chứa các liên kết cho các tên được chỉ định trong thuộc tính co_freevars của code object của hàm.

Đối tượng ô có thuộc tính cell_contents. Điều này có thể được sử dụng để lấy giá trị của ô, cũng như đặt giá trị.

3.2.8.1.2. Thuộc tính có thể ghi đặc biệt

Hầu hết các thuộc tính này kiểm tra loại giá trị được chỉ định:

Thuộc tính

Ý nghĩa

function.__doc__

Chuỗi tài liệu của hàm hoặc None nếu không có.

function.__name__

Tên của hàm. Xem thêm: __name__ attributes.

function.__qualname__

Chức năng của qualified name. Xem thêm: __qualname__ attributes.

Added in version 3.3.

function.__module__

Tên của mô-đun chứa chức năng được xác định hoặc None nếu không có.

function.__defaults__

Một tuple chứa các giá trị parameter mặc định cho những tham số có giá trị mặc định hoặc None nếu không có tham số nào có giá trị mặc định.

function.__code__

Zz000zz đại diện cho phần thân hàm được biên dịch.

function.__dict__

Không gian tên hỗ trợ các thuộc tính hàm tùy ý. Xem thêm: __dict__ attributes.

function.__annotations__

Một dictionary chứa các chú thích của parameters. Các khóa của từ điển là tên tham số và 'return' cho chú thích trả về, nếu được cung cấp. Xem thêm: object.__annotations__.

Thay đổi trong phiên bản 3.14: Chú thích bây giờ là lazily evaluated. Xem PEP 649.

function.__annotate__

annotate function cho hàm này hoặc None nếu hàm không có chú thích. Xem object.__annotate__.

Added in version 3.14.

function.__kwdefaults__

Một dictionary chứa các giá trị mặc định cho parameters chỉ có từ khóa.

function.__type_params__

Một tuple chứa type parameters của generic function.

Added in version 3.12.

Các đối tượng hàm cũng hỗ trợ việc nhận và thiết lập các thuộc tính tùy ý, chẳng hạn như có thể được sử dụng để đính kèm siêu dữ liệu vào các hàm. Ký hiệu dấu chấm thuộc tính thông thường được sử dụng để lấy và đặt các thuộc tính đó.

Việc triển khai hiện tại của CPython chỉ hỗ trợ các thuộc tính hàm trên các hàm do người dùng xác định. Các thuộc tính chức năng trên built-in functions có thể được hỗ trợ trong tương lai.

Thông tin bổ sung về định nghĩa của hàm có thể được lấy từ code object của nó (có thể truy cập thông qua thuộc tính __code__).

3.2.8.2. Phương thức sơ thẩm

Một đối tượng phương thức cá thể kết hợp một lớp, một cá thể lớp và bất kỳ đối tượng có thể gọi được nào (thường là hàm do người dùng định nghĩa).

Thuộc tính chỉ đọc đặc biệt:

method.__self__

Đề cập đến đối tượng thể hiện của lớp mà phương thức là bound

method.__func__

Đề cập đến function object ban đầu

method.__doc__

Tài liệu của phương pháp (giống như method.__func__.__doc__). Một string nếu hàm ban đầu có chuỗi tài liệu, nếu không thì None.

method.__name__

Tên của phương thức (giống như method.__func__.__name__)

method.__module__

Tên của mô-đun mà phương thức được xác định hoặc None nếu không có.

Các phương thức cũng hỗ trợ truy cập (nhưng không thiết lập) các thuộc tính hàm tùy ý trên function object cơ bản.

Các đối tượng phương thức do người dùng định nghĩa có thể được tạo khi lấy một thuộc tính của một lớp (có thể thông qua một thể hiện của lớp đó), nếu thuộc tính đó là đối tượng function object hoặc classmethod do người dùng định nghĩa.

Khi một đối tượng phương thức cá thể được tạo bằng cách truy xuất một function object do người dùng định nghĩa từ một lớp thông qua một trong các cá thể của nó, thuộc tính __self__ của nó là cá thể và đối tượng phương thức được cho là bound. Thuộc tính __func__ của phương thức mới là đối tượng hàm ban đầu.

Khi một đối tượng phương thức cá thể được tạo bằng cách truy xuất một đối tượng classmethod từ một lớp hoặc một thể hiện, thuộc tính __self__ của nó là chính lớp đó và thuộc tính __func__ của nó là đối tượng hàm nằm bên dưới phương thức lớp.

Khi một đối tượng phương thức cá thể được gọi, hàm cơ bản (__func__) sẽ được gọi, chèn cá thể lớp (__self__) vào trước danh sách đối số. Ví dụ: khi C là một lớp chứa định nghĩa cho hàm f()x là một phiên bản của C, việc gọi x.f(1) tương đương với việc gọi C.f(x, 1).

Khi một đối tượng phương thức cá thể có nguồn gốc từ một đối tượng classmethod, "thể hiện lớp" được lưu trữ trong __self__ sẽ thực sự là chính lớp đó, do đó việc gọi x.f(1) hoặc C.f(1) tương đương với việc gọi f(C,1) trong đó f là hàm cơ bản.

Điều quan trọng cần lưu ý là các hàm do người dùng định nghĩa là thuộc tính của một thể hiện lớp không được chuyển đổi thành các phương thức ràng buộc; only này xảy ra khi hàm là một thuộc tính của lớp.

3.2.8.3. Chức năng tạo

Hàm hoặc phương thức sử dụng câu lệnh yield (xem phần Tuyên bố yield) được gọi là generator function. Một hàm như vậy, khi được gọi, luôn trả về một đối tượng iterator có thể được sử dụng để thực thi phần thân của hàm: việc gọi phương thức iterator.__next__() của iterator sẽ khiến hàm thực thi cho đến khi nó cung cấp một giá trị bằng câu lệnh yield. Khi hàm thực thi câu lệnh return hoặc rơi ra khỏi phần cuối, một ngoại lệ StopIteration sẽ xuất hiện và trình vòng lặp sẽ đạt đến phần cuối của tập hợp các giá trị được trả về.

3.2.8.4. Hàm coroutine

Hàm hoặc phương thức được xác định bằng async def được gọi là coroutine function. Hàm như vậy khi được gọi sẽ trả về đối tượng coroutine. Nó có thể chứa các biểu thức await, cũng như các câu lệnh async withasync for. Xem thêm phần Đối tượng Coroutine.

3.2.8.5. Chức năng tạo không đồng bộ

Hàm hoặc phương thức được xác định bằng async def và sử dụng câu lệnh yield được gọi là asynchronous generator function. Hàm như vậy, khi được gọi, sẽ trả về một đối tượng asynchronous iterator có thể được sử dụng trong câu lệnh async for để thực thi phần thân của hàm.

Việc gọi phương thức aiterator.__anext__ của trình vòng lặp không đồng bộ sẽ trả về một awaitable mà khi được chờ đợi sẽ thực thi cho đến khi nó cung cấp một giá trị bằng cách sử dụng biểu thức yield. Khi hàm thực thi một câu lệnh return trống hoặc rơi ra khỏi phần cuối, một ngoại lệ StopAsyncIteration sẽ xuất hiện và trình vòng lặp không đồng bộ sẽ đạt đến phần cuối của tập hợp các giá trị được tạo ra.

3.2.8.6. Các chức năng tích hợp

Đối tượng hàm dựng sẵn là một trình bao bọc xung quanh hàm C. Ví dụ về các hàm tích hợp là len()math.sin() (math là mô-đun tích hợp tiêu chuẩn). Số lượng và loại đối số được xác định bởi hàm C. Thuộc tính chỉ đọc đặc biệt:

  • __doc__ là chuỗi tài liệu của hàm hoặc None nếu không có. Xem function.__doc__.

  • __name__ là tên của hàm. Xem function.__name__.

  • __self__ được đặt thành None (nhưng hãy xem mục tiếp theo).

  • __module__ là tên của mô-đun chứa hàm được xác định hoặc None nếu không có. Xem function.__module__.

3.2.8.7. Các phương pháp tích hợp

Đây thực sự là một cách ngụy trang khác của một hàm dựng sẵn, lần này chứa một đối tượng được truyền cho hàm C dưới dạng một đối số bổ sung ngầm định. Một ví dụ về phương thức tích hợp sẵn là alist.append(), giả sử alist là một đối tượng danh sách. Trong trường hợp này, thuộc tính chỉ đọc đặc biệt __self__ được đặt thành đối tượng được biểu thị bằng alist. (Thuộc tính có cùng ngữ nghĩa như với other instance methods.)

3.2.8.8. Lớp học

Các lớp học có thể gọi được. Các đối tượng này thường hoạt động như các nhà máy cho các phiên bản mới của chính chúng, nhưng có thể có các biến thể đối với các loại lớp ghi đè __new__(). Các đối số của cuộc gọi được chuyển tới __new__() và trong trường hợp điển hình là __init__() để khởi tạo phiên bản mới.

3.2.8.9. Phiên bản lớp

Các thể hiện của các lớp tùy ý có thể được gọi bằng cách định nghĩa phương thức __call__() trong lớp của chúng.

3.2.9. Mô-đun

Mô-đun là đơn vị tổ chức cơ bản của mã Python và được tạo bởi import system khi được gọi bằng câu lệnh import hoặc bằng cách gọi các hàm như importlib.import_module()__import__() tích hợp. Đối tượng mô-đun có một không gian tên được triển khai bởi đối tượng dictionary (đây là từ điển được tham chiếu bởi thuộc tính __globals__ của các hàm được xác định trong mô-đun). Các tham chiếu thuộc tính được dịch sang dạng tra cứu trong từ điển này, ví dụ: m.x tương đương với m.__dict__["x"]. Đối tượng mô-đun không chứa đối tượng mã được sử dụng để khởi tạo mô-đun (vì nó không cần thiết sau khi quá trình khởi tạo hoàn tất).

Việc gán thuộc tính cập nhật từ điển không gian tên của mô-đun, ví dụ: m.x = 1 tương đương với m.__dict__["x"] = 1.

3.2.9.2. Các thuộc tính có thể ghi khác trên đối tượng mô-đun

Ngoài các thuộc tính liên quan đến nhập được liệt kê ở trên, các đối tượng mô-đun cũng có các thuộc tính có thể ghi sau:

module.__doc__

Chuỗi tài liệu của mô-đun hoặc None nếu không có. Xem thêm: __doc__ attributes.

module.__annotations__

Một từ điển chứa variable annotations được thu thập trong quá trình thực thi phần thân mô-đun. Để biết các phương pháp hay nhất khi làm việc với __annotations__, hãy xem annotationlib.

Thay đổi trong phiên bản 3.14: Chú thích bây giờ là lazily evaluated. Xem PEP 649.

module.__annotate__

annotate function cho mô-đun này hoặc None nếu mô-đun không có chú thích. Xem thêm: thuộc tính __annotate__.

Added in version 3.14.

3.2.9.3. Từ điển mô-đun

Các đối tượng mô-đun cũng có thuộc tính chỉ đọc đặc biệt sau:

module.__dict__

Không gian tên của mô-đun như một đối tượng từ điển. Duy nhất trong số các thuộc tính được liệt kê ở đây, __dict__ không thể được truy cập dưới dạng biến toàn cục từ bên trong mô-đun; nó chỉ có thể được truy cập như một thuộc tính trên các đối tượng mô-đun.

Do cách CPython xóa từ điển mô-đun nên từ điển mô-đun sẽ bị xóa khi mô-đun nằm ngoài phạm vi ngay cả khi từ điển vẫn còn tham chiếu trực tiếp. Để tránh điều này, hãy sao chép từ điển hoặc giữ lại mô-đun trong khi sử dụng trực tiếp từ điển của nó.

3.2.10. Lớp tùy chỉnh

Các loại lớp tùy chỉnh thường được tạo theo định nghĩa lớp (xem phần Định nghĩa lớp). Một lớp có một không gian tên được thực hiện bởi một đối tượng từ điển. Các tham chiếu thuộc tính lớp được dịch sang dạng tra cứu trong từ điển này, ví dụ: C.x được dịch sang C.__dict__["x"] (mặc dù có một số hook cho phép các phương tiện định vị thuộc tính khác). Khi không tìm thấy tên thuộc tính ở đó, việc tìm kiếm thuộc tính sẽ tiếp tục trong các lớp cơ sở. Việc tìm kiếm các lớp cơ sở này sử dụng thứ tự phân giải phương thức C3 hoạt động chính xác ngay cả khi có cấu trúc kế thừa 'kim cương' trong đó có nhiều đường dẫn kế thừa dẫn trở lại tổ tiên chung. Bạn có thể tìm thêm thông tin chi tiết về C3 MRO được Python sử dụng tại Thứ tự phân giải phương thức Python 2.3.

Khi một tham chiếu thuộc tính lớp (chẳng hạn như đối với lớp C) mang lại một đối tượng phương thức lớp, nó sẽ được chuyển đổi thành một đối tượng phương thức cá thể có thuộc tính __self__C. Khi nó mang lại một đối tượng staticmethod, nó sẽ được chuyển đổi thành đối tượng được bao bọc bởi đối tượng phương thức tĩnh. Xem phần Triển khai mô tả để biết cách khác trong đó các thuộc tính được truy xuất từ ​​một lớp có thể khác với các thuộc tính thực sự có trong __dict__ của nó.

Phép gán thuộc tính lớp cập nhật từ điển của lớp, không bao giờ là từ điển của lớp cơ sở.

Một đối tượng lớp có thể được gọi (xem ở trên) để tạo ra một thể hiện của lớp (xem bên dưới).

3.2.10.1. Thuộc tính đặc biệt

Thuộc tính

Ý nghĩa

type.__name__

Tên của lớp học. Xem thêm: __name__ attributes.

type.__qualname__

Lớp học qualified name. Xem thêm: __qualname__ attributes.

type.__module__

Tên của mô-đun trong đó lớp được xác định.

type.__dict__

Zz000zz cung cấp chế độ xem chỉ đọc cho không gian tên của lớp. Xem thêm: __dict__ attributes.

type.__bases__

Một tuple chứa các cơ sở của lớp. Trong hầu hết các trường hợp, đối với lớp được xác định là class X(A, B, C), X.__bases__ sẽ chính xác bằng (A, B, C).

type.__base__

Lớp cơ sở duy nhất trong chuỗi kế thừa chịu trách nhiệm bố trí bộ nhớ của các phiên bản. Thuộc tính này tương ứng với tp_base ở cấp độ C.

type.__doc__

Chuỗi tài liệu của lớp hoặc None nếu không xác định. Không được kế thừa bởi các lớp con.

type.__annotations__

Một từ điển chứa variable annotations được thu thập trong quá trình thực thi nội dung lớp. Xem thêm: __annotations__ attributes.

Để biết các phương pháp hay nhất khi làm việc với __annotations__, vui lòng xem annotationlib. Sử dụng annotationlib.get_annotations() thay vì truy cập trực tiếp vào thuộc tính này.

Cảnh báo

Việc truy cập thuộc tính __annotations__ trực tiếp trên một đối tượng lớp có thể trả về các chú thích cho lớp sai, cụ thể trong một số trường hợp nhất định trong đó lớp, lớp cơ sở của nó hoặc siêu dữ liệu được xác định trong from __future__ import annotations. Xem 749 để biết chi tiết.

Thuộc tính này không tồn tại trên một số lớp dựng sẵn nhất định. Trên các lớp do người dùng định nghĩa không có __annotations__, nó là một từ điển trống.

Thay đổi trong phiên bản 3.14: Chú thích bây giờ là lazily evaluated. Xem PEP 649.

type.__annotate__()

annotate function cho lớp này hoặc None nếu lớp không có chú thích. Xem thêm: __annotate__ attributes.

Added in version 3.14.

type.__type_params__

Một tuple chứa type parameters của generic class.

Added in version 3.12.

type.__static_attributes__

Một tuple chứa tên các thuộc tính của lớp này được gán thông qua self.X từ bất kỳ hàm nào trong phần thân của nó.

Added in version 3.13.

type.__firstlineno__

Số dòng của dòng đầu tiên trong định nghĩa lớp, bao gồm cả phần trang trí. Việc đặt thuộc tính __module__ sẽ xóa mục __firstlineno__ khỏi từ điển của loại.

Added in version 3.13.

type.__mro__

tuple của các lớp được xem xét khi tìm kiếm các lớp cơ sở trong quá trình phân giải phương thức.

3.2.10.2. Phương pháp đặc biệt

Ngoài các thuộc tính đặc biệt được mô tả ở trên, tất cả các lớp Python còn có sẵn hai phương thức sau:

type.mro()

Phương thức này có thể được ghi đè bằng siêu dữ liệu để tùy chỉnh thứ tự phân giải phương thức cho các phiên bản của nó. Nó được gọi khi khởi tạo lớp và kết quả của nó được lưu trữ trong __mro__.

type.__subclasses__()

Mỗi lớp giữ một danh sách các tham chiếu yếu đến các lớp con trực tiếp của nó. Phương thức này trả về danh sách tất cả các tham chiếu đó vẫn còn tồn tại. Danh sách theo thứ tự định nghĩa. Ví dụ:

>>> lớp A: đậu
>>> lớp B(A): đậu
>>> A.__lớp con__()
[<lớp 'B'>]

3.2.11. Phiên bản lớp

Một thể hiện của lớp được tạo bằng cách gọi một đối tượng lớp (xem ở trên). Một thể hiện của lớp có một không gian tên được triển khai như một từ điển, đây là nơi đầu tiên tìm kiếm các tham chiếu thuộc tính. Khi không tìm thấy thuộc tính ở đó và lớp của cá thể có thuộc tính có tên đó, việc tìm kiếm sẽ tiếp tục với các thuộc tính của lớp. Nếu một thuộc tính lớp được tìm thấy là một đối tượng hàm do người dùng định nghĩa, nó sẽ được chuyển đổi thành một đối tượng phương thức cá thể có thuộc tính __self__ là cá thể. Các đối tượng phương thức tĩnh và phương thức lớp cũng được chuyển đổi; xem ở trên trong phần "Lớp học". Xem phần Triển khai mô tả để biết cách khác trong đó các thuộc tính của một lớp được truy xuất thông qua các thể hiện của nó có thể khác với các đối tượng thực sự được lưu trữ trong __dict__ của lớp. Nếu không tìm thấy thuộc tính lớp nào và lớp của đối tượng có phương thức __getattr__() thì phương thức đó được gọi để đáp ứng việc tra cứu.

Việc gán và xóa thuộc tính cập nhật từ điển của thể hiện, không bao giờ là từ điển của lớp. Nếu lớp có phương thức __setattr__() hoặc __delattr__(), thì phương thức này sẽ được gọi thay vì cập nhật trực tiếp từ điển phiên bản.

Các thể hiện của lớp có thể giả vờ là số, chuỗi hoặc ánh xạ nếu chúng có các phương thức với một số tên đặc biệt nhất định. Xem phần Tên phương thức đặc biệt.

3.2.11.1. Thuộc tính đặc biệt

object.__class__

Lớp mà một thể hiện của lớp thuộc về.

object.__dict__

Một từ điển hoặc đối tượng ánh xạ khác được sử dụng để lưu trữ các thuộc tính (có thể ghi) của đối tượng. Không phải tất cả các phiên bản đều có thuộc tính __dict__; xem phần trên __khe__ để biết thêm chi tiết.

3.2.12. Đối tượng I/O (còn được gọi là đối tượng tệp)

Zz000zz đại diện cho một tệp đang mở. Có sẵn nhiều phím tắt khác nhau để tạo các đối tượng tệp: hàm dựng sẵn open(), cũng như os.popen(), os.fdopen() và phương thức makefile() của các đối tượng socket (và có thể bằng các hàm hoặc phương thức khác được cung cấp bởi các mô-đun mở rộng).

Các đối tượng tệp triển khai các phương thức phổ biến được liệt kê bên dưới để đơn giản hóa việc sử dụng mã chung. Họ dự kiến ​​​​sẽ là Với Trình quản lý bối cảnh câu lệnh.

Các đối tượng sys.stdin, sys.stdoutsys.stderr được khởi tạo để lưu trữ các đối tượng tương ứng với các luồng đầu vào, đầu ra và lỗi tiêu chuẩn của trình thông dịch; tất cả chúng đều mở ở chế độ văn bản và do đó tuân theo giao diện được xác định bởi lớp trừu tượng io.TextIOBase.

file.read(size=-1, /)

Truy xuất dữ liệu lên tới size từ tệp. Để thuận tiện nếu size không được chỉ định hoặc -1 truy xuất tất cả dữ liệu có sẵn.

file.write(data, /)

Lưu trữ data vào tập tin.

file.close()

Xóa mọi bộ đệm và đóng tệp cơ bản.

3.2.13. Các loại nội bộ

Một số loại được trình thông dịch sử dụng nội bộ sẽ được hiển thị cho người dùng. Định nghĩa của chúng có thể thay đổi theo các phiên bản tương lai của trình thông dịch, nhưng chúng được đề cập ở đây để đảm bảo đầy đủ.

3.2.13.1. Đối tượng mã

Các đối tượng mã đại diện cho mã Python thực thi byte-compiled hoặc bytecode. Sự khác biệt giữa đối tượng mã và đối tượng hàm là đối tượng hàm chứa tham chiếu rõ ràng đến toàn cục của hàm (mô-đun mà nó được xác định), trong khi đối tượng mã không chứa ngữ cảnh; các giá trị đối số mặc định cũng được lưu trữ trong đối tượng hàm chứ không phải trong đối tượng mã (vì chúng biểu thị các giá trị được tính toán trong thời gian chạy). Không giống như các đối tượng hàm, các đối tượng mã là bất biến và không chứa tham chiếu (trực tiếp hoặc gián tiếp) đến các đối tượng có thể thay đổi.

3.2.13.1.1. Thuộc tính chỉ đọc đặc biệt
codeobject.co_name

Tên chức năng

codeobject.co_qualname

Tên hàm đủ điều kiện

Added in version 3.11.

codeobject.co_argcount

Tổng số parameters vị trí (bao gồm các tham số chỉ có vị trí và các tham số có giá trị mặc định) mà hàm có

codeobject.co_posonlyargcount

Số lượng parameters chỉ có vị trí (bao gồm các đối số có giá trị mặc định) mà hàm có

codeobject.co_kwonlyargcount

Số lượng parameters chỉ có từ khóa (bao gồm các đối số có giá trị mặc định) mà hàm có

codeobject.co_nlocals

Số lượng local variables mà hàm sử dụng (bao gồm cả tham số)

codeobject.co_varnames

Một tuple chứa tên của các biến cục bộ trong hàm (bắt đầu bằng tên tham số)

codeobject.co_cellvars

Một tuple chứa tên của local variables được tham chiếu từ ít nhất một nested scope bên trong hàm

codeobject.co_freevars

Một tuple chứa tên của free (closure) variablesnested scope tham chiếu ở phạm vi bên ngoài. Xem thêm function.__closure__.

Lưu ý: bao gồm các tham chiếu đến tên chung và tên dựng sẵn not.

codeobject.co_code

Một chuỗi biểu thị chuỗi lệnh bytecode trong hàm

codeobject.co_consts

Một tuple chứa các chữ được bytecode sử dụng trong hàm

codeobject.co_names

Một tuple chứa các tên được bytecode sử dụng trong hàm

codeobject.co_filename

Tên của tệp mà mã được biên dịch

codeobject.co_firstlineno

Số dòng của dòng đầu tiên của hàm

codeobject.co_lnotab

Một chuỗi mã hóa ánh xạ từ độ lệch bytecode sang số dòng. Để biết chi tiết, hãy xem mã nguồn của trình thông dịch.

Sắp loại bỏ từ phiên bản 3.12: Thuộc tính này của các đối tượng mã không được dùng nữa và có thể bị xóa trong Python 3.15.

codeobject.co_stacksize

Kích thước ngăn xếp cần thiết của đối tượng mã

codeobject.co_flags

Một integer mã hóa một số cờ cho trình thông dịch.

Các bit cờ sau đây được xác định cho co_flags: bit 0x04 được đặt nếu hàm sử dụng cú pháp *arguments để chấp nhận số lượng đối số vị trí tùy ý; bit 0x08 được đặt nếu hàm sử dụng cú pháp **keywords để chấp nhận các đối số từ khóa tùy ý; bit 0x20 được đặt nếu hàm này là một trình tạo. Xem Cờ bit đối tượng mã để biết chi tiết về ngữ nghĩa của từng cờ có thể xuất hiện.

Các khai báo tính năng trong tương lai (ví dụ: from __future__ import division) cũng sử dụng các bit trong co_flags để cho biết liệu một đối tượng mã có được biên dịch với một tính năng cụ thể được bật hay không. Xem compiler_flag.

Các bit khác trong co_flags được dành riêng để sử dụng nội bộ.

Nếu một đối tượng mã đại diện cho một hàm và có chuỗi tài liệu, thì bit CO_HAS_DOCSTRING được đặt trong co_flags và mục đầu tiên trong co_consts là chuỗi tài liệu của hàm.

3.2.13.1.2. Các phương thức trên đối tượng mã
codeobject.co_positions()

Trả về một giá trị có thể lặp lại trên các vị trí mã nguồn của từng lệnh bytecode trong đối tượng mã.

Trình vòng lặp trả về tuples chứa (start_line, end_line, start_column, end_column). Bộ i-th tương ứng với vị trí của mã nguồn được biên dịch thành đơn vị mã i-th. Thông tin cột là độ lệch byte utf-8 được lập chỉ mục 0 trên dòng nguồn đã cho.

Thông tin vị trí này có thể bị thiếu. Danh sách không đầy đủ các trường hợp điều này có thể xảy ra:

  • Chạy trình thông dịch với -X no_debug_ranges.

  • Đang tải tệp pyc được biên dịch trong khi sử dụng -X no_debug_ranges.

  • Vị trí các bộ dữ liệu tương ứng với các lệnh nhân tạo.

  • Không thể biểu thị số dòng và số cột do các hạn chế cụ thể khi triển khai.

Khi điều này xảy ra, một số hoặc tất cả các phần tử trong bộ có thể là None.

Added in version 3.11.

Ghi chú

Tính năng này yêu cầu lưu trữ các vị trí cột trong đối tượng mã, điều này có thể làm tăng nhẹ mức sử dụng đĩa của các tệp Python đã biên dịch hoặc mức sử dụng bộ nhớ trình thông dịch. Để tránh lưu trữ thông tin bổ sung và/hoặc hủy kích hoạt việc in thông tin truy nguyên bổ sung, có thể sử dụng cờ dòng lệnh -X no_debug_ranges hoặc biến môi trường PYTHONNODEBUGRANGES.

codeobject.co_lines()

Trả về một trình vòng lặp mang lại thông tin về các phạm vi liên tiếp của bytecodes. Mỗi mục mang lại là một (start, end, lineno) tuple:

  • start (một int) đại diện cho phần bù (bao gồm) điểm bắt đầu của phạm vi bytecode

  • end (một int) đại diện cho phần bù (độc quyền) của phần cuối của phạm vi bytecode

  • linenoint đại diện cho số dòng của phạm vi bytecode hoặc None nếu mã byte trong phạm vi đã cho không có số dòng

Các vật phẩm thu được sẽ có các thuộc tính sau:

  • Phạm vi đầu tiên mang lại sẽ có start bằng 0.

  • Phạm vi (start, end) sẽ không giảm và liên tục. Nghĩa là, đối với bất kỳ cặp tuples nào, start của cặp thứ hai sẽ bằng end của cặp thứ nhất.

  • Không có phạm vi nào sẽ bị lùi: end >= start cho tất cả các bộ ba.

  • tuple cuối cùng mang lại sẽ có end bằng kích thước của bytecode.

Cho phép phạm vi độ rộng bằng 0, trong đó start == end. Phạm vi độ rộng bằng 0 được sử dụng cho các dòng có trong mã nguồn nhưng đã bị trình biên dịch bytecode loại bỏ.

Added in version 3.10.

Xem thêm

PEP 626 - Số dòng chính xác để gỡ lỗi và các công cụ khác.

Zz001zz đã giới thiệu phương pháp co_lines().

codeobject.replace(**kwargs)

Trả về bản sao của đối tượng mã với các giá trị mới cho các trường được chỉ định.

Các đối tượng mã cũng được hỗ trợ bởi hàm chung copy.replace().

Added in version 3.8.

3.2.13.2. Đóng khung đồ vật

Các đối tượng khung đại diện cho các khung thực thi. Chúng có thể xuất hiện trong traceback objects và cũng được chuyển đến các chức năng theo dõi đã đăng ký.

3.2.13.2.1. Thuộc tính chỉ đọc đặc biệt
frame.f_back

Trỏ tới khung ngăn xếp trước đó (hướng tới người gọi) hoặc None nếu đây là khung ngăn xếp dưới cùng

frame.f_code

Zz000zz đang được thực thi trong khung này. Việc truy cập thuộc tính này sẽ tạo ra auditing event object.__getattr__ với các đối số obj"f_code".

frame.f_locals

Ánh xạ được khung sử dụng để tra cứu local variables. Nếu khung tham chiếu đến optimized scope, điều này có thể trả về một đối tượng proxy ghi qua.

Thay đổi trong phiên bản 3.13: Trả lại proxy cho phạm vi được tối ưu hóa.

frame.f_globals

Từ điển được frame sử dụng để tra cứu global variables

frame.f_builtins

Từ điển được frame sử dụng để tra cứu built-in (intrinsic) names

frame.f_lasti

"Lệnh chính xác" của đối tượng khung (đây là chỉ mục trong chuỗi bytecode của code object)

frame.f_generator

Đối tượng generator hoặc coroutine sở hữu khung này hoặc None nếu khung là chức năng bình thường.

Added in version 3.14.

3.2.13.2.2. Thuộc tính có thể ghi đặc biệt
frame.f_trace

Nếu không phải là None thì đây là hàm được gọi cho nhiều sự kiện khác nhau trong quá trình thực thi mã (hàm này được trình gỡ lỗi sử dụng). Thông thường, một sự kiện sẽ được kích hoạt cho mỗi dòng nguồn mới (xem f_trace_lines).

frame.f_trace_lines

Đặt thuộc tính này thành False để tắt kích hoạt sự kiện theo dõi cho từng dòng nguồn.

frame.f_trace_opcodes

Đặt thuộc tính này thành True để cho phép yêu cầu các sự kiện trên mỗi mã opcode. Lưu ý rằng điều này có thể dẫn đến hành vi của trình thông dịch không xác định nếu các ngoại lệ do hàm theo dõi đưa ra thoát khỏi hàm được theo dõi.

frame.f_lineno

Số dòng hiện tại của khung -- việc ghi vào khung này từ bên trong hàm theo dõi sẽ nhảy tới dòng đã cho (chỉ dành cho khung dưới cùng). Trình gỡ lỗi có thể triển khai lệnh Nhảy (còn gọi là Đặt câu lệnh tiếp theo) bằng cách ghi vào thuộc tính này.

3.2.13.2.3. Phương thức đối tượng khung

Các đối tượng khung hỗ trợ một phương thức:

frame.clear()

Phương pháp này xóa tất cả các tham chiếu đến local variables được giữ trong khung. Ngoài ra, nếu khung thuộc về generator, trình tạo sẽ được hoàn thiện. Điều này giúp phá vỡ các chu trình tham chiếu liên quan đến các đối tượng khung (ví dụ: khi bắt một exception và lưu trữ traceback của nó để sử dụng sau này).

RuntimeError được nâng lên nếu khung hiện đang được thực thi hoặc bị treo.

Added in version 3.4.

Thay đổi trong phiên bản 3.13: Cố gắng xóa khung bị treo sẽ tăng RuntimeError (như trường hợp luôn xảy ra khi thực thi khung).

3.2.13.3. Đối tượng truy nguyên

Các đối tượng truy nguyên biểu thị dấu vết ngăn xếp của exception. Đối tượng truy nguyên được tạo ngầm khi xảy ra ngoại lệ và cũng có thể được tạo rõ ràng bằng cách gọi types.TracebackType.

Thay đổi trong phiên bản 3.7: Các đối tượng theo dõi hiện có thể được khởi tạo rõ ràng từ mã Python.

Đối với các truy nguyên được tạo ngầm, khi tìm kiếm một trình xử lý ngoại lệ sẽ giải phóng ngăn xếp thực thi, ở mỗi cấp độ không liên kết, một đối tượng truy nguyên sẽ được chèn vào phía trước truy nguyên hiện tại. Khi một trình xử lý ngoại lệ được nhập vào, dấu vết ngăn xếp sẽ được cung cấp cho chương trình. (Xem phần Tuyên bố try.) Nó có thể được truy cập dưới dạng mục thứ ba của bộ dữ liệu được trả về bởi sys.exc_info() và dưới dạng thuộc tính __traceback__ của ngoại lệ bị bắt.

Khi chương trình không chứa trình xử lý phù hợp, dấu vết ngăn xếp sẽ được ghi (được định dạng rõ ràng) vào luồng lỗi tiêu chuẩn; nếu trình thông dịch có tính tương tác thì nó cũng được cung cấp cho người dùng dưới dạng sys.last_traceback.

Đối với các truy nguyên được tạo rõ ràng, người tạo truy nguyên có trách nhiệm xác định cách liên kết các thuộc tính tb_next để tạo thành một dấu vết ngăn xếp đầy đủ.

Thuộc tính chỉ đọc đặc biệt:

traceback.tb_frame

Trỏ tới việc thực thi frame ở cấp độ hiện tại.

Việc truy cập thuộc tính này sẽ tạo ra một auditing event object.__getattr__ với các đối số obj"tb_frame".

traceback.tb_lineno

Cung cấp số dòng nơi xảy ra ngoại lệ

traceback.tb_lasti

Cho biết "hướng dẫn chính xác".

Số dòng và lệnh cuối cùng trong traceback có thể khác với số dòng của frame object nếu ngoại lệ xảy ra trong câu lệnh try không khớp với mệnh đề ngoại trừ hoặc với mệnh đề finally.

traceback.tb_next

Thuộc tính có thể ghi đặc biệt tb_next là cấp độ tiếp theo trong dấu vết ngăn xếp (hướng tới khung xảy ra ngoại lệ) hoặc None nếu không có cấp độ tiếp theo.

Thay đổi trong phiên bản 3.7: Thuộc tính này bây giờ có thể ghi được

3.2.13.4. Cắt lát đối tượng

Các đối tượng Slice được sử dụng để biểu diễn các lát cắt cho các phương thức __getitem__(). Chúng cũng được tạo bởi chức năng slice() tích hợp.

Thuộc tính chỉ đọc đặc biệt: start là giới hạn dưới; stop là giới hạn trên; step là giá trị bước; mỗi cái là None nếu bị bỏ qua. Các thuộc tính này có thể có bất kỳ loại nào.

Các đối tượng Slice hỗ trợ một phương thức:

slice.indices(self, length)

Phương thức này lấy một đối số nguyên duy nhất length và tính toán thông tin về lát cắt mà đối tượng lát cắt sẽ mô tả nếu được áp dụng cho một chuỗi các mục length. Nó trả về một bộ ba số nguyên; tương ứng đây là các chỉ số startstopstep hoặc độ dài sải chân của lát cắt. Các chỉ số bị thiếu hoặc nằm ngoài giới hạn được xử lý theo cách phù hợp với các lát cắt thông thường.

3.2.13.5. Đối tượng phương thức tĩnh

Các đối tượng phương thức tĩnh cung cấp một cách để loại bỏ sự biến đổi của các đối tượng hàm thành các đối tượng phương thức được mô tả ở trên. Đối tượng phương thức tĩnh là một trình bao bọc xung quanh bất kỳ đối tượng nào khác, thường là đối tượng phương thức do người dùng xác định. Khi một đối tượng phương thức tĩnh được lấy ra từ một lớp hoặc một thể hiện của lớp, đối tượng thực sự được trả về là đối tượng được bao bọc, không chịu bất kỳ sự chuyển đổi nào nữa. Các đối tượng phương thức tĩnh cũng có thể gọi được. Các đối tượng phương thức tĩnh được tạo bởi hàm tạo staticmethod() tích hợp.

3.2.13.6. Đối tượng phương thức lớp

Một đối tượng phương thức lớp, giống như một đối tượng phương thức tĩnh, là một trình bao bọc xung quanh một đối tượng khác làm thay đổi cách truy xuất đối tượng đó từ các lớp và các thể hiện của lớp. Hành vi của các đối tượng phương thức lớp khi truy xuất như vậy được mô tả ở trên, dưới phần "instance methods". Các đối tượng phương thức lớp được tạo bởi hàm tạo classmethod() tích hợp.

3.3. Tên phương thức đặc biệt

Một lớp có thể thực hiện một số thao tác nhất định được gọi bằng cú pháp đặc biệt (chẳng hạn như các phép toán số học hoặc chỉ số dưới và cắt) bằng cách xác định các phương thức có tên đặc biệt. Đây là cách tiếp cận của Python đối với operator overloading, cho phép các lớp xác định hành vi của riêng chúng đối với các toán tử ngôn ngữ. Ví dụ: nếu một lớp định nghĩa một phương thức có tên __getitem__()x là một phiên bản của lớp này thì x[i] gần tương đương với type(x).__getitem__(x, i). Trừ khi được đề cập, các nỗ lực thực hiện một thao tác sẽ tạo ra ngoại lệ khi không có phương thức thích hợp nào được xác định (thường là AttributeError hoặc TypeError).

Việc đặt một phương thức đặc biệt thành None cho biết thao tác tương ứng không khả dụng. Ví dụ: nếu một lớp đặt __iter__() thành None, thì lớp đó không thể lặp lại được, do đó, việc gọi iter() trên các phiên bản của nó sẽ tăng TypeError (mà không quay trở lại __getitem__()). [2]

Khi triển khai một lớp mô phỏng bất kỳ loại tích hợp nào, điều quan trọng là việc mô phỏng chỉ được triển khai ở mức độ phù hợp với đối tượng được mô hình hóa. Ví dụ: một số chuỗi có thể hoạt động tốt với việc truy xuất các phần tử riêng lẻ, nhưng việc trích xuất một lát cắt có thể không có ý nghĩa. (Một ví dụ về điều này là giao diện NodeList trong Mô hình đối tượng tài liệu của W3C.)

3.3.1. Tùy chỉnh cơ bản

object.__new__(cls[, ...])

Được gọi để tạo một thể hiện mới của lớp cls. __new__() là một phương thức tĩnh (được đặt trong vỏ đặc biệt nên bạn không cần phải khai báo như vậy) lấy lớp mà phiên bản được yêu cầu làm đối số đầu tiên. Các đối số còn lại là những đối số được truyền cho biểu thức hàm tạo đối tượng (lệnh gọi lớp). Giá trị trả về của __new__() phải là phiên bản đối tượng mới (thường là phiên bản của cls).

Các cách triển khai điển hình sẽ tạo một phiên bản mới của lớp bằng cách gọi phương thức __new__() của siêu lớp bằng cách sử dụng super().__new__(cls[, ...]) với các đối số thích hợp, sau đó sửa đổi phiên bản mới được tạo nếu cần trước khi trả về nó.

Nếu __new__() được gọi trong quá trình xây dựng đối tượng và nó trả về một phiên bản của cls, thì phương thức __init__() của phiên bản mới sẽ được gọi như __init__(self[, ...]), trong đó self là phiên bản mới và các đối số còn lại giống như được truyền cho hàm tạo đối tượng.

Nếu __new__() không trả về một phiên bản của cls thì phương thức __init__() của phiên bản mới sẽ không được gọi.

__new__() chủ yếu nhằm mục đích cho phép các lớp con thuộc loại không thể thay đổi (như int, str hoặc tuple) tùy chỉnh việc tạo phiên bản. Nó cũng thường được ghi đè trong siêu dữ liệu tùy chỉnh để tùy chỉnh việc tạo lớp.

object.__init__(self[, ...])

Được gọi sau khi phiên bản đã được tạo (bởi __new__()), nhưng trước khi nó được trả về cho người gọi. Các đối số là những đối số được truyền cho biểu thức hàm tạo của lớp. Nếu một lớp cơ sở có một phương thức __init__(), thì phương thức __init__() của lớp dẫn xuất, nếu có, phải gọi nó một cách rõ ràng để đảm bảo khởi tạo đúng phần lớp cơ sở của cá thể; ví dụ: super().__init__([args...]).

__new__()__init__() phối hợp với nhau trong việc xây dựng các đối tượng (__new__() để tạo ra nó và __init__() để tùy chỉnh nó), nên __init__() không thể trả về giá trị không phải None; làm như vậy sẽ khiến TypeError được nâng lên khi chạy.

object.__del__(self)

Được gọi khi instance sắp bị hủy. Đây còn được gọi là bộ hoàn thiện hoặc bộ hủy (không đúng cách). Nếu một lớp cơ sở có phương thức __del__(), thì phương thức __del__() của lớp dẫn xuất, nếu có, phải gọi nó một cách rõ ràng để đảm bảo xóa đúng phần lớp cơ sở của cá thể.

Phương thức __del__() có thể trì hoãn việc hủy phiên bản bằng cách tạo một tham chiếu mới cho phiên bản đó (mặc dù không được khuyến nghị!) Đây được gọi là đối tượng resurrection. Việc __del__() có được gọi lần thứ hai hay không khi một đối tượng được phục hồi sắp bị phá hủy còn phụ thuộc vào việc triển khai hay không; việc triển khai CPython hiện tại chỉ gọi nó một lần.

Không đảm bảo rằng các phương thức __del__() được gọi cho các đối tượng vẫn tồn tại khi trình thông dịch thoát. weakref.finalize cung cấp một cách đơn giản để đăng ký hàm dọn dẹp để gọi khi một đối tượng được thu gom rác.

Ghi chú

del x không gọi trực tiếp x.__del__() --- cái trước giảm số lượng tham chiếu cho x đi một và cái sau chỉ được gọi khi số tham chiếu của x đạt đến 0.

Chu trình tham chiếu có thể ngăn chặn số lượng tham chiếu của một đối tượng về 0. Trong trường hợp này, chu trình sau đó sẽ được cyclic garbage collector phát hiện và xóa. Nguyên nhân phổ biến của chu kỳ tham chiếu là khi có một ngoại lệ xảy ra trong một biến cục bộ. Sau đó, các địa phương của khung sẽ tham chiếu đến ngoại lệ, tham chiếu đến dấu vết của chính nó, tham chiếu đến các địa phương của tất cả các khung được ghi lại trong dấu vết.

Xem thêm

Tài liệu cho mô-đun gc.

Cảnh báo

Do các trường hợp bấp bênh trong đó các phương thức __del__() được gọi, các ngoại lệ xảy ra trong quá trình thực thi chúng sẽ bị bỏ qua và thay vào đó, một cảnh báo sẽ được in ra sys.stderr. Đặc biệt:

  • __del__() có thể được gọi khi mã tùy ý đang được thực thi, kể cả từ bất kỳ luồng tùy ý nào. Nếu __del__() cần khóa hoặc gọi bất kỳ tài nguyên chặn nào khác, nó có thể bị bế tắc vì tài nguyên có thể đã bị lấy bởi mã bị gián đoạn để thực thi __del__().

  • __del__() có thể được thực thi trong khi tắt trình thông dịch. Kết quả là, các biến toàn cục mà nó cần truy cập (bao gồm các mô-đun khác) có thể đã bị xóa hoặc được đặt thành None. Python đảm bảo rằng các biến toàn cục có tên bắt đầu bằng một dấu gạch dưới sẽ bị xóa khỏi mô-đun của chúng trước khi các biến toàn cục khác bị xóa; nếu không có tham chiếu nào khác đến các hình cầu như vậy tồn tại, điều này có thể giúp đảm bảo rằng các mô-đun đã nhập vẫn có sẵn tại thời điểm phương thức __del__() được gọi.

object.__repr__(self)

Được gọi bằng hàm tích hợp repr() để tính toán biểu diễn chuỗi "chính thức" của một đối tượng. Nếu có thể, biểu thức này sẽ trông giống như một biểu thức Python hợp lệ có thể được sử dụng để tạo lại một đối tượng có cùng giá trị (trong một môi trường thích hợp). Nếu điều này là không thể, một chuỗi có dạng <...some useful description...> sẽ được trả về. Giá trị trả về phải là một đối tượng chuỗi. Nếu một lớp định nghĩa __repr__() chứ không phải __str__(), thì __repr__() cũng được sử dụng khi cần có một chuỗi biểu diễn "không chính thức" của các phiên bản của lớp đó.

Điều này thường được sử dụng để gỡ lỗi, vì vậy điều quan trọng là cách trình bày phải giàu thông tin và rõ ràng. Việc triển khai mặc định được cung cấp bởi chính lớp object.

object.__str__(self)

Được gọi bởi str(object), cách triển khai __format__() mặc định và hàm print() tích hợp để tính toán biểu diễn chuỗi "không chính thức" hoặc có thể in độc đáo của một đối tượng. Giá trị trả về phải là đối tượng str.

Phương thức này khác với object.__repr__() ở chỗ không có kỳ vọng rằng __str__() trả về một biểu thức Python hợp lệ: có thể sử dụng một cách biểu diễn ngắn gọn hoặc thuận tiện hơn.

Việc triển khai mặc định được xác định bởi loại object tích hợp gọi object.__repr__().

object.__bytes__(self)

Được gọi bởi bytes để tính toán biểu diễn chuỗi byte của một đối tượng. Điều này sẽ trả về một đối tượng bytes. Bản thân lớp object không cung cấp phương thức này.

object.__format__(self, format_spec)

Được gọi bằng hàm tích hợp format() và bằng cách mở rộng, đánh giá formatted string literals và phương thức str.format() để tạo ra biểu diễn chuỗi "được định dạng" của một đối tượng. Đối số format_spec là một chuỗi chứa mô tả về các tùy chọn định dạng mong muốn. Việc giải thích đối số format_spec tùy thuộc vào loại triển khai __format__(), tuy nhiên, hầu hết các lớp sẽ ủy quyền định dạng cho một trong các loại có sẵn hoặc sử dụng cú pháp tùy chọn định dạng tương tự.

Xem Đặc tả định dạng ngôn ngữ nhỏ để biết mô tả về cú pháp định dạng chuẩn.

Giá trị trả về phải là một đối tượng chuỗi.

Việc triển khai mặc định của lớp object phải được cung cấp một chuỗi format_spec trống. Nó ủy quyền cho __str__().

Thay đổi trong phiên bản 3.4: Bản thân phương thức __format__ của object sẽ tăng TypeError nếu truyền bất kỳ chuỗi nào không trống.

Thay đổi trong phiên bản 3.7: object.__format__(x, '') hiện tương đương với str(x) thay vì format(str(x), '').

object.__lt__(self, other)
object.__le__(self, other)
object.__eq__(self, other)
object.__ne__(self, other)
object.__gt__(self, other)
object.__ge__(self, other)

Đây được gọi là phương pháp "so sánh phong phú". Sự tương ứng giữa các ký hiệu toán tử và tên phương thức như sau: x<y gọi x.__lt__(y), x<=y gọi x.__le__(y), x==y gọi x.__eq__(y), x!=y gọi x.__ne__(y), x>y gọi x.__gt__(y)x>=y gọi x.__ge__(y).

Một phương thức so sánh phong phú có thể trả về NotImplemented đơn lẻ nếu nó không triển khai thao tác cho một cặp đối số nhất định. Theo quy ước, FalseTrue được trả về để so sánh thành công. Tuy nhiên, các phương thức này có thể trả về bất kỳ giá trị nào, vì vậy nếu toán tử so sánh được sử dụng trong ngữ cảnh Boolean (ví dụ: trong điều kiện của câu lệnh if), Python sẽ gọi bool() trên giá trị để xác định xem kết quả là đúng hay sai.

Theo mặc định, object triển khai __eq__() bằng cách sử dụng is, trả về NotImplemented trong trường hợp so sánh sai: True if x is y else NotImplemented. Đối với __ne__(), theo mặc định, nó ủy quyền cho __eq__() và đảo ngược kết quả trừ khi đó là NotImplemented. Không có mối quan hệ ngụ ý nào khác giữa các toán tử so sánh hoặc việc triển khai mặc định; ví dụ: sự thật của (x<y or x==y) không bao hàm x<=y. Để tự động tạo các hoạt động đặt hàng từ một thao tác gốc duy nhất, hãy xem functools.total_ordering().

Theo mặc định, lớp object cung cấp các triển khai nhất quán với So sánh giá trị: so sánh đẳng thức theo danh tính đối tượng và so sánh thứ tự nâng cao TypeError. Mỗi phương thức mặc định có thể trực tiếp tạo ra các kết quả này nhưng cũng có thể trả về NotImplemented.

Xem đoạn về __hash__() để biết một số lưu ý quan trọng về cách tạo đối tượng hashable hỗ trợ các hoạt động so sánh tùy chỉnh và có thể sử dụng làm khóa từ điển.

Không có phiên bản đối số hoán đổi của các phương thức này (được sử dụng khi đối số bên trái không hỗ trợ thao tác nhưng đối số bên phải thì có); đúng hơn, __lt__()__gt__() là hình ảnh phản chiếu của nhau, __le__()__ge__() là hình ảnh phản chiếu của nhau, còn __eq__()__ne__() là hình ảnh phản chiếu của chính chúng. Nếu các toán hạng có nhiều kiểu khác nhau và kiểu của toán hạng bên phải là lớp con trực tiếp hoặc gián tiếp của kiểu toán hạng bên trái thì phương thức phản ánh của toán hạng bên phải có mức độ ưu tiên, nếu không thì phương thức của toán hạng bên trái sẽ được ưu tiên. Phân lớp ảo không được xem xét.

Khi không có phương thức thích hợp nào trả về bất kỳ giá trị nào ngoài NotImplemented, các toán tử ==!= sẽ lần lượt quay trở lại isis not.

object.__hash__(self)

Được gọi bằng hàm tích hợp hash() và dành cho các thao tác trên các thành viên của bộ sưu tập băm bao gồm set, frozensetdict. Phương thức __hash__() sẽ trả về một số nguyên. Thuộc tính bắt buộc duy nhất là các đối tượng so sánh bằng nhau có cùng giá trị băm; Bạn nên kết hợp các giá trị băm của các thành phần của đối tượng cũng đóng vai trò so sánh các đối tượng với nhau bằng cách đóng gói chúng thành một bộ và băm bộ đó. Ví dụ:

chắc chắn __hash__(tự):
    hàm băm trả về((self.name, self.nick, self.color))

Ghi chú

hash() cắt bớt giá trị được trả về từ phương thức __hash__() tùy chỉnh của đối tượng thành kích thước của Py_ssize_t. Đây thường là 8 byte trên bản dựng 64 bit và 4 byte trên bản dựng 32 bit. Nếu __hash__() của một đối tượng phải tương tác trên các bản dựng có kích thước bit khác nhau, hãy nhớ kiểm tra độ rộng trên tất cả các bản dựng được hỗ trợ. Một cách dễ dàng để làm điều này là sử dụng python -c "import sys; print(sys.hash_info.width)".

Nếu một lớp không định nghĩa phương thức __eq__() thì nó cũng không nên định nghĩa thao tác __hash__(); nếu nó xác định __eq__() chứ không phải __hash__(), thì các phiên bản của nó sẽ không thể sử dụng được làm mục trong bộ sưu tập có thể băm. Nếu một lớp xác định các đối tượng có thể thay đổi và triển khai phương thức __eq__() thì lớp đó không nên triển khai __hash__(), vì việc triển khai các bộ sưu tập hashable yêu cầu giá trị băm của khóa là không thay đổi (nếu giá trị băm của đối tượng thay đổi thì nó sẽ nằm trong nhóm băm sai).

Các lớp do người dùng định nghĩa có các phương thức __eq__()__hash__() theo mặc định (được kế thừa từ lớp object); với chúng, tất cả các đối tượng đều so sánh không bằng nhau (ngoại trừ với chính chúng) và x.__hash__() trả về một giá trị thích hợp sao cho x == y ngụ ý cả x is yhash(x) == hash(y).

Một lớp ghi đè __eq__() và không xác định __hash__() sẽ có __hash__() được đặt ngầm định thành None. Khi phương thức __hash__() của một lớp là None, các phiên bản của lớp đó sẽ đưa ra một TypeError thích hợp khi một chương trình cố gắng truy xuất giá trị băm của chúng và cũng sẽ được xác định chính xác là không thể băm được khi kiểm tra isinstance(obj, collections.abc.Hashable).

Nếu một lớp ghi đè __eq__() cần giữ lại việc triển khai __hash__() từ lớp cha, thì trình thông dịch phải được thông báo rõ ràng điều này bằng cách đặt __hash__ = <ParentClass>.__hash__.

Nếu một lớp không ghi đè __eq__() muốn ngăn chặn hỗ trợ băm thì lớp đó phải bao gồm __hash__ = None trong định nghĩa lớp. Một lớp xác định __hash__() của chính nó mà tăng TypeError một cách rõ ràng sẽ bị xác định không chính xác là có thể băm được bằng lệnh gọi isinstance(obj, collections.abc.Hashable).

Ghi chú

Theo mặc định, các giá trị __hash__() của các đối tượng str và byte được "ướp muối" bằng một giá trị ngẫu nhiên không thể đoán trước. Mặc dù chúng không đổi trong một quy trình Python riêng lẻ, nhưng chúng không thể dự đoán được giữa các lần gọi Python lặp đi lặp lại.

Điều này nhằm mục đích cung cấp khả năng bảo vệ chống lại tình trạng từ chối dịch vụ do các đầu vào được lựa chọn cẩn thận nhằm khai thác hiệu suất trong trường hợp xấu nhất của thao tác chèn chính tả, độ phức tạp O(n2). Xem https://ocert.org/advisories/ocert-2011-003.html để biết chi tiết.

Việc thay đổi giá trị băm ảnh hưởng đến thứ tự lặp của tập hợp. Python chưa bao giờ đưa ra đảm bảo về thứ tự này (và nó thường thay đổi giữa các bản dựng 32 bit và 64 bit).

Xem thêm PYTHONHASHSEED.

Thay đổi trong phiên bản 3.3: Tính năng ngẫu nhiên băm được bật theo mặc định.

object.__bool__(self)

Được gọi để triển khai kiểm tra giá trị thực và hoạt động tích hợp bool(); nên trả về False hoặc True. Khi phương thức này không được xác định, __len__() sẽ được gọi nếu nó được xác định và đối tượng được coi là đúng nếu kết quả của nó khác 0. Nếu một lớp không xác định __len__() hay __bool__() (điều này đúng với chính lớp object), thì tất cả các phiên bản của nó đều được coi là đúng.

3.3.2. Tùy chỉnh quyền truy cập thuộc tính

Các phương thức sau đây có thể được định nghĩa để tùy chỉnh ý nghĩa của việc truy cập thuộc tính (sử dụng, gán hoặc xóa x.name) cho các thể hiện của lớp.

object.__getattr__(self, name)

Được gọi khi truy cập thuộc tính mặc định không thành công với AttributeError (__getattribute__() tăng AttributeErrorname không phải là thuộc tính phiên bản hoặc thuộc tính trong cây lớp cho self; hoặc __get__() của thuộc tính name tăng AttributeError). Phương thức này sẽ trả về giá trị thuộc tính (được tính toán) hoặc đưa ra ngoại lệ AttributeError. Bản thân lớp object không cung cấp phương thức này.

Lưu ý rằng nếu thuộc tính được tìm thấy thông qua cơ chế thông thường, __getattr__() sẽ không được gọi. (Đây là sự bất đối xứng có chủ ý giữa __getattr__()__setattr__().) Điều này được thực hiện vì lý do hiệu quả và vì nếu không thì __getattr__() sẽ không có cách nào để truy cập các thuộc tính khác của phiên bản. Lưu ý rằng ít nhất đối với các biến mẫu, bạn có thể kiểm soát hoàn toàn bằng cách không chèn bất kỳ giá trị nào vào từ điển thuộc tính mẫu (mà thay vào đó chèn chúng vào một đối tượng khác). Xem phương pháp __getattribute__() bên dưới để biết cách thực sự có được toàn quyền kiểm soát quyền truy cập thuộc tính.

object.__getattribute__(self, name)

Được gọi vô điều kiện để thực hiện truy cập thuộc tính cho các thể hiện của lớp. Nếu lớp cũng định nghĩa __getattr__() thì lớp sau sẽ không được gọi trừ khi __getattribute__() gọi nó một cách rõ ràng hoặc tăng AttributeError. Phương thức này sẽ trả về giá trị thuộc tính (được tính toán) hoặc đưa ra một ngoại lệ AttributeError. Để tránh đệ quy vô hạn trong phương thức này, việc triển khai nó phải luôn gọi phương thức lớp cơ sở có cùng tên để truy cập bất kỳ thuộc tính nào nó cần, ví dụ: object.__getattribute__(self, name).

Ghi chú

Phương thức này vẫn có thể bị bỏ qua khi tra cứu các phương thức đặc biệt do lệnh gọi ngầm thông qua cú pháp ngôn ngữ hoặc built-in functions. Xem Tra cứu phương pháp đặc biệt.

Đối với các quyền truy cập thuộc tính nhạy cảm nhất định, hãy tăng auditing event object.__getattr__ với các đối số objname.

object.__setattr__(self, name, value)

Được gọi khi cố gắng gán thuộc tính. Điều này được gọi thay vì cơ chế thông thường (tức là lưu trữ giá trị trong từ điển mẫu). name là tên thuộc tính, value là giá trị được gán cho nó.

Nếu __setattr__() muốn gán cho một thuộc tính instance, nó nên gọi phương thức lớp cơ sở có cùng tên, ví dụ: object.__setattr__(self, name, value).

Đối với một số phép gán thuộc tính nhạy cảm nhất định, hãy tăng auditing event object.__setattr__ với các đối số obj, name, value.

object.__delattr__(self, name)

Giống như __setattr__() nhưng để xóa thuộc tính thay vì gán. Điều này chỉ nên được thực hiện nếu del obj.name có ý nghĩa đối với đối tượng.

Đối với một số thao tác xóa thuộc tính nhạy cảm nhất định, hãy tăng auditing event object.__delattr__ với các đối số objname.

object.__dir__(self)

Được gọi khi dir() được gọi trên đối tượng. Một lần lặp phải được trả lại. dir() chuyển đổi iterable được trả về thành một danh sách và sắp xếp nó.

3.3.2.1. Tùy chỉnh quyền truy cập thuộc tính mô-đun

module.__getattr__()
module.__dir__()

Tên đặc biệt __getattr____dir__ cũng có thể được sử dụng để tùy chỉnh quyền truy cập vào các thuộc tính mô-đun. Hàm __getattr__ ở cấp mô-đun phải chấp nhận một đối số là tên của thuộc tính và trả về giá trị được tính toán hoặc tăng AttributeError. Nếu không tìm thấy thuộc tính trên đối tượng mô-đun thông qua tra cứu thông thường, tức là object.__getattribute__(), thì __getattr__ sẽ được tìm kiếm trong mô-đun __dict__ trước khi đưa ra AttributeError. Nếu tìm thấy, nó sẽ được gọi với tên thuộc tính và kết quả được trả về.

Hàm __dir__ không được chấp nhận đối số và trả về một chuỗi lặp đại diện cho các tên có thể truy cập được trên mô-đun. Nếu có, chức năng này sẽ ghi đè tìm kiếm dir() tiêu chuẩn trên mô-đun.

module.__class__

Để tùy chỉnh chi tiết hơn hành vi mô-đun (cài đặt thuộc tính, thuộc tính, v.v.), người ta có thể đặt thuộc tính __class__ của đối tượng mô-đun thành lớp con của types.ModuleType. Ví dụ:

hệ thống nhập khẩu
từ các loại nhập ModuleType

lớp VerboseModule(ModuleType):
    chắc chắn __repr__(tự):
        return f'Verbose {self.__name__}'

    def __setattr__(self, attr, value):
        print(f'Đặt {attr}...')
        super().__setattr__(attr, giá trị)

sys.modules[__name__].__class__ = VerboseModule

Ghi chú

Việc xác định mô-đun __getattr__ và cài đặt mô-đun __class__ chỉ ảnh hưởng đến việc tra cứu được thực hiện bằng cú pháp truy cập thuộc tính -- việc truy cập trực tiếp vào các phần tổng thể của mô-đun (cho dù bằng mã trong mô-đun hay thông qua tham chiếu đến từ điển toàn cục của mô-đun) không bị ảnh hưởng.

Thay đổi trong phiên bản 3.5: Thuộc tính mô-đun __class__ hiện có thể ghi được.

Added in version 3.7: Thuộc tính mô-đun __getattr____dir__.

Xem thêm

PEP 562 - Mô-đun __getattr__ và __dir__

Mô tả các chức năng __getattr____dir__ trên mô-đun.

3.3.2.2. Triển khai mô tả

Các phương thức sau chỉ áp dụng khi một thể hiện của lớp chứa phương thức (còn gọi là lớp descriptor) xuất hiện trong lớp owner (bộ mô tả phải có trong từ điển lớp của chủ sở hữu hoặc trong từ điển lớp của một trong các cha mẹ của nó). Trong các ví dụ bên dưới, "thuộc tính" đề cập đến thuộc tính có tên là khóa của thuộc tính trong __dict__ của lớp chủ sở hữu. Bản thân lớp object không triển khai bất kỳ giao thức nào trong số này.

object.__get__(self, instance, owner=None)

Được gọi để lấy thuộc tính của lớp chủ sở hữu (quyền truy cập thuộc tính lớp) hoặc của một thể hiện của lớp đó (quyền truy cập thuộc tính thể hiện). Đối số owner tùy chọn là lớp chủ sở hữu, trong khi instance là phiên bản mà thuộc tính được truy cập thông qua hoặc None khi thuộc tính được truy cập thông qua owner.

Phương thức này sẽ trả về giá trị thuộc tính được tính toán hoặc đưa ra ngoại lệ AttributeError.

PEP 252 chỉ định rằng __get__() có thể gọi được với một hoặc hai đối số. Các bộ mô tả tích hợp sẵn của Python hỗ trợ thông số kỹ thuật này; tuy nhiên, có khả năng một số công cụ của bên thứ ba có bộ mô tả yêu cầu cả hai đối số. Việc triển khai __getattribute__() của Python luôn chuyển cả hai đối số cho dù chúng có được yêu cầu hay không.

object.__set__(self, instance, value)

Được gọi để đặt thuộc tính trên một thể hiện instance của lớp chủ sở hữu thành một giá trị mới, value.

Lưu ý, việc thêm __set__() hoặc __delete__() sẽ thay đổi loại bộ mô tả thành "bộ mô tả dữ liệu". Xem Gọi mô tả để biết thêm chi tiết.

object.__delete__(self, instance)

Được gọi để xóa thuộc tính trên một thể hiện instance của lớp chủ sở hữu.

Các phiên bản của bộ mô tả cũng có thể có thuộc tính __objclass__:

object.__objclass__

Thuộc tính __objclass__ được mô-đun inspect diễn giải là chỉ định lớp nơi đối tượng này được xác định (việc thiết lập thuộc tính này một cách thích hợp có thể hỗ trợ việc xem xét nội tâm thời gian chạy của các thuộc tính lớp động). Đối với các lệnh gọi được, nó có thể chỉ ra rằng một phiên bản của loại đã cho (hoặc một lớp con) được mong đợi hoặc được yêu cầu làm đối số vị trí đầu tiên (ví dụ: CPython đặt thuộc tính này cho các phương thức không liên kết được triển khai trong C).

3.3.2.3. Gọi mô tả

Nói chung, bộ mô tả là một thuộc tính đối tượng có "hành vi liên kết", một thuộc tính có quyền truy cập thuộc tính đã bị ghi đè bởi các phương thức trong giao thức bộ mô tả: __get__(), __set__()__delete__(). Nếu bất kỳ phương thức nào trong số đó được xác định cho một đối tượng thì nó được gọi là một bộ mô tả.

Hành vi mặc định để truy cập thuộc tính là lấy, đặt hoặc xóa thuộc tính khỏi từ điển của đối tượng. Ví dụ: a.x có chuỗi tra cứu bắt đầu bằng a.__dict__['x'], sau đó là type(a).__dict__['x'] và tiếp tục đến các lớp cơ sở của type(a) ngoại trừ siêu dữ liệu.

Tuy nhiên, nếu giá trị tra cứu là một đối tượng xác định một trong các phương thức mô tả thì Python có thể ghi đè hành vi mặc định và gọi phương thức mô tả thay thế. Trường hợp điều này xảy ra trong chuỗi ưu tiên phụ thuộc vào phương thức mô tả nào được xác định và cách chúng được gọi.

Điểm bắt đầu cho việc gọi bộ mô tả là một ràng buộc, a.x. Cách tập hợp các đối số phụ thuộc vào a:

Gọi trực tiếp

Lệnh gọi đơn giản và ít phổ biến nhất là khi mã người dùng gọi trực tiếp một phương thức mô tả: x.__get__(a).

Ràng buộc cá thể

Nếu liên kết với một phiên bản đối tượng, a.x sẽ được chuyển thành lệnh gọi: type(a).__dict__['x'].__get__(a, type(a)).

Ràng buộc lớp

Nếu liên kết với một lớp, A.x sẽ được chuyển thành lệnh gọi: A.__dict__['x'].__get__(None, A).

siêu ràng buộc

Tra cứu theo dấu chấm chẳng hạn như super(A, a).x tìm kiếm a.__class__.__mro__ để tìm lớp cơ sở B theo sau A và sau đó trả về B.__dict__['x'].__get__(a, A). Nếu không phải là bộ mô tả, x sẽ được trả về không thay đổi.

Đối với các ràng buộc thể hiện, độ ưu tiên của việc gọi bộ mô tả phụ thuộc vào phương thức mô tả nào được xác định. Một bộ mô tả có thể xác định bất kỳ sự kết hợp nào của __get__(), __set__()__delete__(). Nếu nó không xác định __get__() thì việc truy cập vào thuộc tính sẽ trả về chính đối tượng mô tả trừ khi có một giá trị trong từ điển đối tượng của đối tượng. Nếu bộ mô tả xác định __set__() và/hoặc __delete__() thì đó là bộ mô tả dữ liệu; nếu nó không xác định thì đó là một bộ mô tả phi dữ liệu. Thông thường, các bộ mô tả dữ liệu xác định cả __get__()__set__(), trong khi các bộ mô tả không phải dữ liệu chỉ có phương thức __get__(). Bộ mô tả dữ liệu có __get__()__set__() (và/hoặc __delete__()) được xác định luôn ghi đè định nghĩa lại trong từ điển phiên bản. Ngược lại, các bộ mô tả phi dữ liệu có thể bị ghi đè bởi các phiên bản.

Các phương thức Python (bao gồm cả các phương thức được trang trí bằng @staticmethod@classmethod) được triển khai dưới dạng mô tả phi dữ liệu. Theo đó, các instance có thể định nghĩa lại và ghi đè các phương thức. Điều này cho phép các cá thể riêng lẻ có được các hành vi khác với các cá thể khác trong cùng một lớp.

Hàm property() được triển khai dưới dạng mô tả dữ liệu. Theo đó, các thể hiện không thể ghi đè hành vi của một thuộc tính.

3.3.2.4. __khe__

__slots__ cho phép chúng tôi khai báo rõ ràng các thành viên dữ liệu (như thuộc tính) và từ chối việc tạo __dict____weakref__ (trừ khi được khai báo rõ ràng trong __slots__ hoặc có sẵn trong cha mẹ.)

Dung lượng được tiết kiệm khi sử dụng __dict__ có thể rất đáng kể. Tốc độ tra cứu thuộc tính cũng có thể được cải thiện đáng kể.

object.__slots__

Biến lớp này có thể được gán một chuỗi, có thể lặp hoặc chuỗi các chuỗi có tên biến được sử dụng bởi các phiên bản. __slots__ dành không gian cho các biến được khai báo và ngăn việc tự động tạo __dict____weakref__ cho mỗi phiên bản.

Những lưu ý khi sử dụng __slots__:

  • Khi kế thừa từ một lớp không có __slots__, thuộc tính __dict____weakref__ của các phiên bản sẽ luôn có thể truy cập được.

  • Nếu không có biến __dict__, các phiên bản không thể được gán các biến mới không được liệt kê trong định nghĩa __slots__. Nỗ lực gán cho một tên biến không được liệt kê sẽ tăng AttributeError. Nếu muốn gán động các biến mới, thì hãy thêm '__dict__' vào chuỗi các chuỗi trong khai báo __slots__.

  • Nếu không có biến __weakref__ cho mỗi phiên bản, các lớp xác định __slots__ sẽ không hỗ trợ weak references cho các phiên bản của nó. Nếu cần hỗ trợ tham chiếu yếu thì hãy thêm '__weakref__' vào chuỗi các chuỗi trong khai báo __slots__.

  • __slots__ được triển khai ở cấp lớp bằng cách tạo descriptors cho mỗi tên biến. Do đó, các thuộc tính lớp không thể được sử dụng để đặt giá trị mặc định cho các biến thể hiện được xác định bởi __slots__; nếu không, thuộc tính lớp sẽ ghi đè lên phần gán mô tả.

  • Hành động của khai báo __slots__ không bị giới hạn ở lớp nơi nó được xác định. __slots__ được khai báo trong lớp cha có sẵn trong lớp con. Tuy nhiên, các phiên bản của lớp con con sẽ nhận được __dict____weakref__ trừ khi lớp con đó cũng xác định __slots__ (chỉ nên chứa tên của bất kỳ vị trí additional nào).

  • Nếu một lớp xác định một vị trí cũng được xác định trong một lớp cơ sở, thì biến thể hiện được xác định bởi vị trí của lớp cơ sở sẽ không thể truy cập được (ngoại trừ bằng cách truy xuất bộ mô tả của nó trực tiếp từ lớp cơ sở). Điều này làm cho ý nghĩa của chương trình không được xác định. Trong tương lai, một kiểm tra có thể được thêm vào để ngăn chặn điều này.

  • TypeError sẽ được tăng lên nếu __slots__ không trống được xác định cho một lớp bắt nguồn từ "variable-length" built-in type chẳng hạn như int, bytestuple.

  • Bất kỳ iterable không phải chuỗi nào cũng có thể được gán cho __slots__.

  • Nếu dictionary được sử dụng để gán __slots__, các khóa từ điển sẽ được sử dụng làm tên vị trí. Các giá trị của từ điển có thể được sử dụng để cung cấp các chuỗi tài liệu cho mỗi thuộc tính sẽ được inspect.getdoc() nhận dạng và hiển thị trong đầu ra của help().

  • Phép gán __class__ chỉ hoạt động nếu cả hai lớp có cùng __slots__.

  • Có thể sử dụng Multiple inheritance với nhiều lớp cha mẹ có khe cắm, nhưng chỉ một lớp cha mẹ được phép có các thuộc tính được tạo bởi các vị trí (các cơ sở khác phải có bố cục vị trí trống) - vi phạm tăng TypeError.

  • Nếu iterator được sử dụng cho __slots__ thì descriptor sẽ được tạo cho mỗi giá trị của trình vòng lặp. Tuy nhiên, thuộc tính __slots__ sẽ là một trình lặp trống.

3.3.3. Tùy chỉnh việc tạo lớp

Bất cứ khi nào một lớp kế thừa từ một lớp khác, __init_subclass__() sẽ được gọi trên lớp cha. Bằng cách này, có thể viết các lớp thay đổi hành vi của các lớp con. Điều này liên quan chặt chẽ đến các trình trang trí lớp, nhưng trong đó các trình trang trí lớp chỉ ảnh hưởng đến lớp cụ thể mà chúng được áp dụng, thì __init_subclass__ chỉ áp dụng cho các lớp con trong tương lai của lớp xác định phương thức.

classmethod object.__init_subclass__(cls)

Phương thức này được gọi bất cứ khi nào lớp chứa được phân lớp. cls sau đó sẽ là lớp con mới. Nếu được định nghĩa như một phương thức cá thể thông thường, thì phương thức này được chuyển đổi hoàn toàn thành một phương thức lớp.

Các đối số từ khóa được cấp cho một lớp mới sẽ được chuyển tới __init_subclass__ của lớp cha. Để tương thích với các lớp khác sử dụng __init_subclass__, người ta nên loại bỏ các đối số từ khóa cần thiết và chuyển các đối số từ khóa khác sang lớp cơ sở, như trong

Lớp triết gia:
    def __init_subclass__(cls, /, default_name, **kwargs):
        super().__init_subclass__(**kwargs)
        cls.default_name = tên_mặc định

lớp AustralianPhilosopher(Triết gia, default_name="Bruce"):
    vượt qua

Việc triển khai mặc định object.__init_subclass__ không làm gì cả nhưng sẽ gây ra lỗi nếu nó được gọi với bất kỳ đối số nào.

Ghi chú

Gợi ý siêu dữ liệu metaclass được sử dụng bởi phần còn lại của loại máy móc và không bao giờ được chuyển sang triển khai __init_subclass__. Siêu dữ liệu thực tế (chứ không phải gợi ý rõ ràng) có thể được truy cập dưới dạng type(cls).

Added in version 3.6.

Khi một lớp được tạo, type.__new__() sẽ quét các biến của lớp và thực hiện lệnh gọi lại những biến có móc __set_name__().

object.__set_name__(self, owner, name)

Tự động được gọi vào thời điểm lớp sở hữu owner được tạo. Đối tượng đã được gán cho name trong lớp đó:

lớp A:
    x = C() # Automatically gọi: x.__set_name__(A, 'x')

Nếu biến lớp được gán sau khi lớp được tạo, __set_name__() sẽ không được gọi tự động. Nếu cần, __set_name__() có thể được gọi trực tiếp:

lớp A:
   vượt qua

c = C()
A.x = c # The hook không được gọi
c.__set_name__(A, 'x') # Manually gọi hook

Xem Tạo đối tượng lớp để biết thêm chi tiết.

Added in version 3.6.

3.3.3.1. Siêu lớp

Theo mặc định, các lớp được xây dựng bằng type(). Nội dung lớp được thực thi trong một không gian tên mới và tên lớp được liên kết cục bộ với kết quả của type(name, bases, namespace).

Quá trình tạo lớp có thể được tùy chỉnh bằng cách chuyển đối số từ khóa metaclass trong dòng định nghĩa lớp hoặc bằng cách kế thừa từ một lớp hiện có có chứa đối số như vậy. Trong ví dụ sau, cả MyClassMySubclass đều là phiên bản của Meta:

lớp Meta(loại):
    vượt qua

lớp MyClass(metaclass=Meta):
    vượt qua

lớp MySubclass(MyClass):
    vượt qua

Bất kỳ đối số từ khóa nào khác được chỉ định trong định nghĩa lớp đều được chuyển qua tất cả các hoạt động siêu dữ liệu được mô tả bên dưới.

Khi một định nghĩa lớp được thực thi, các bước sau sẽ xảy ra:

  • các mục MRO được giải quyết;

  • siêu dữ liệu thích hợp được xác định;

  • không gian tên lớp đã được chuẩn bị;

  • thân lớp được thực thi;

  • đối tượng lớp được tạo ra.

3.3.3.2. Giải quyết các mục MRO

object.__mro_entries__(self, bases)

Nếu cơ sở xuất hiện trong định nghĩa lớp không phải là một phiên bản của type thì phương thức __mro_entries__() sẽ được tìm kiếm trên cơ sở đó. Nếu tìm thấy phương thức __mro_entries__(), cơ sở sẽ được thay thế bằng kết quả của lệnh gọi tới __mro_entries__() khi tạo lớp. Phương thức này được gọi với bộ dữ liệu cơ sở ban đầu được truyền cho tham số bases và phải trả về một bộ dữ liệu các lớp sẽ được sử dụng thay vì cơ sở. Bộ dữ liệu trả về có thể trống: trong những trường hợp này, cơ sở ban đầu bị bỏ qua.

Xem thêm

types.resolve_bases()

Tự động giải quyết các cơ sở không phải là phiên bản của type.

types.get_original_bases()

Truy xuất "cơ sở ban đầu" của một lớp trước khi sửa đổi bằng __mro_entries__().

PEP 560

Hỗ trợ cốt lõi cho việc gõ mô-đun và các loại chung.

3.3.3.3. Xác định siêu dữ liệu thích hợp

Siêu dữ liệu thích hợp cho định nghĩa lớp được xác định như sau:

  • nếu không có cơ sở và siêu dữ liệu rõ ràng nào được đưa ra thì type() sẽ được sử dụng;

  • nếu một siêu dữ liệu rõ ràng được đưa ra và not là một phiên bản của type() thì siêu dữ liệu đó sẽ được sử dụng trực tiếp làm siêu dữ liệu;

  • nếu một phiên bản của type() được đưa ra dưới dạng siêu dữ liệu rõ ràng hoặc các cơ sở được xác định thì siêu dữ liệu dẫn xuất nhiều nhất sẽ được sử dụng.

Siêu dữ liệu dẫn xuất nhiều nhất được chọn từ siêu dữ liệu được chỉ định rõ ràng (nếu có) và siêu dữ liệu (tức là type(cls)) của tất cả các lớp cơ sở được chỉ định. Siêu lớp có nguồn gốc nhiều nhất là siêu lớp là một kiểu con của all trong số các siêu lớp ứng cử viên này. Nếu không có siêu dữ liệu ứng cử viên nào đáp ứng tiêu chí đó thì định nghĩa lớp sẽ thất bại với TypeError.

3.3.3.4. Chuẩn bị không gian tên lớp

Khi siêu dữ liệu thích hợp đã được xác định thì không gian tên lớp sẽ được chuẩn bị. Nếu siêu dữ liệu có thuộc tính __prepare__ thì nó được gọi là namespace = metaclass.__prepare__(name, bases, **kwds) (trong đó các đối số từ khóa bổ sung, nếu có, đến từ định nghĩa lớp). Phương thức __prepare__ nên được triển khai dưới dạng classmethod. Không gian tên được trả về bởi __prepare__ sẽ được chuyển vào __new__, nhưng khi đối tượng lớp cuối cùng được tạo thì không gian tên đó sẽ được sao chép vào một dict mới.

Nếu siêu dữ liệu không có thuộc tính __prepare__ thì không gian tên lớp sẽ được khởi tạo dưới dạng ánh xạ có thứ tự trống.

Xem thêm

PEP 3115 - Siêu dữ liệu trong Python 3000

Giới thiệu hook không gian tên __prepare__

3.3.3.5. Thực thi thân lớp

Phần thân lớp được thực thi (xấp xỉ) dưới dạng exec(body, globals(), namespace). Sự khác biệt chính so với lệnh gọi thông thường tới exec() là phạm vi từ vựng cho phép nội dung lớp (bao gồm mọi phương thức) tham chiếu tên từ phạm vi hiện tại và phạm vi bên ngoài khi định nghĩa lớp xảy ra bên trong một hàm.

Tuy nhiên, ngay cả khi định nghĩa lớp xảy ra bên trong hàm, các phương thức được định nghĩa bên trong lớp vẫn không thể thấy tên được định nghĩa ở phạm vi lớp. Các biến lớp phải được truy cập thông qua tham số đầu tiên của các phương thức lớp hoặc thể hiện hoặc thông qua tham chiếu __class__ có phạm vi từ vựng ngầm được mô tả trong phần tiếp theo.

3.3.3.6. Tạo đối tượng lớp

Khi không gian tên lớp đã được điền bằng cách thực thi phần thân lớp, đối tượng lớp sẽ được tạo bằng cách gọi metaclass(name, bases, namespace, **kwds) (các từ khóa bổ sung được truyền ở đây giống như các từ khóa được truyền cho __prepare__).

Đối tượng lớp này là đối tượng sẽ được tham chiếu bởi dạng không đối số của super(). __class__ là một tham chiếu đóng ngầm được tạo bởi trình biên dịch nếu bất kỳ phương thức nào trong nội dung lớp tham chiếu đến __class__ hoặc super. Điều này cho phép dạng đối số 0 của super() xác định chính xác lớp đang được xác định dựa trên phạm vi từ vựng, trong khi lớp hoặc phiên bản được sử dụng để thực hiện lệnh gọi hiện tại được xác định dựa trên đối số đầu tiên được truyền cho phương thức.

Trong CPython 3.6 trở lên, ô __class__ được chuyển đến siêu dữ liệu dưới dạng mục nhập __classcell__ trong không gian tên lớp. Nếu có, điều này phải được truyền tới lệnh gọi type.__new__ để lớp được khởi tạo chính xác. Không làm như vậy sẽ dẫn đến RuntimeError trong Python 3.8.

Khi sử dụng siêu dữ liệu mặc định type hoặc bất kỳ siêu dữ liệu nào cuối cùng gọi type.__new__, các bước tùy chỉnh bổ sung sau đây sẽ được gọi sau khi tạo đối tượng lớp:

  1. Phương thức type.__new__ thu thập tất cả các thuộc tính trong không gian tên lớp xác định phương thức __set_name__();

  2. Các phương thức __set_name__ đó được gọi với lớp được xác định và tên được gán của thuộc tính cụ thể đó;

  3. Hook __init_subclass__() được gọi trên lớp cha trực tiếp của lớp mới theo thứ tự phân giải phương thức của nó.

Sau khi đối tượng lớp được tạo, nó được chuyển tới các trình trang trí lớp có trong định nghĩa lớp (nếu có) và đối tượng kết quả được liên kết trong không gian tên cục bộ như lớp được xác định.

Khi một lớp mới được tạo bởi type.__new__, đối tượng được cung cấp làm tham số không gian tên sẽ được sao chép sang ánh xạ có thứ tự mới và đối tượng ban đầu sẽ bị loại bỏ. Bản sao mới được bọc trong một proxy chỉ đọc, trở thành thuộc tính __dict__ của đối tượng lớp.

Xem thêm

PEP 3135 - Siêu phẩm mới

Mô tả tham chiếu đóng __class__ ngầm định

3.3.3.7. Sử dụng cho siêu dữ liệu

Khả năng sử dụng siêu dữ liệu là vô hạn. Một số ý tưởng đã được khám phá bao gồm enum, ghi nhật ký, kiểm tra giao diện, ủy quyền tự động, tạo thuộc tính tự động, proxy, khung và khóa/đồng bộ hóa tài nguyên tự động.

3.3.4. Tùy chỉnh kiểm tra cá thể và lớp con

Các phương pháp sau đây được sử dụng để ghi đè hành vi mặc định của các hàm dựng sẵn isinstance()issubclass().

Đặc biệt, siêu dữ liệu abc.ABCMeta triển khai các phương thức này để cho phép bổ sung các Lớp cơ sở trừu tượng (ABC) làm "lớp cơ sở ảo" cho bất kỳ lớp hoặc loại nào (bao gồm cả các loại dựng sẵn), bao gồm cả các ABC khác.

type.__instancecheck__(self, instance)

Trả về true nếu instance được coi là một phiên bản (trực tiếp hoặc gián tiếp) của class. Nếu được xác định, sẽ được gọi để triển khai isinstance(instance, class).

type.__subclasscheck__(self, subclass)

Trả về true nếu subclass được coi là lớp con (trực tiếp hoặc gián tiếp) của class. Nếu được xác định, sẽ được gọi để triển khai issubclass(subclass, class).

Lưu ý rằng các phương thức này được tra cứu theo kiểu (siêu lớp) của một lớp. Chúng không thể được định nghĩa là các phương thức lớp trong lớp thực tế. Điều này nhất quán với việc tra cứu các phương thức đặc biệt được gọi trên các thể hiện, chỉ trong trường hợp này bản thân thể hiện đó là một lớp.

Xem thêm

PEP 3119 - Giới thiệu các lớp cơ sở trừu tượng

Bao gồm thông số kỹ thuật để tùy chỉnh hành vi isinstance()issubclass() thông qua __instancecheck__()__subclasscheck__(), với động lực cho chức năng này trong bối cảnh thêm các Lớp cơ sở trừu tượng (xem mô-đun abc) vào ngôn ngữ.

3.3.5. Mô phỏng các loại chung

Khi sử dụng type annotations, việc parameterize a generic type sử dụng ký hiệu dấu ngoặc vuông của Python thường rất hữu ích. Ví dụ: chú thích list[int] có thể được sử dụng để biểu thị list trong đó tất cả các phần tử đều thuộc loại int.

Xem thêm

PEP 484 - Gợi ý gõ

Giới thiệu khung công tác chú thích kiểu của Python

Generic Alias Types

Tài liệu cho các đối tượng đại diện cho các lớp chung được tham số hóa

Thuốc gốc, user-defined genericstyping.Generic

Tài liệu về cách triển khai các lớp chung có thể được tham số hóa trong thời gian chạy và được trình kiểm tra kiểu tĩnh hiểu được.

Một lớp generally chỉ có thể được tham số hóa nếu nó định nghĩa phương thức lớp đặc biệt __class_getitem__().

classmethod object.__class_getitem__(cls, key)

Trả về một đối tượng biểu thị sự chuyên môn hóa của một lớp chung theo các đối số kiểu được tìm thấy trong key.

Khi được định nghĩa trên một lớp, __class_getitem__() tự động là một phương thức lớp. Như vậy, không cần thiết phải trang trí nó bằng @classmethod khi nó được xác định.

3.3.5.1. Mục đích của __class_getitem__

Mục đích của __class_getitem__() là cho phép tham số hóa thời gian chạy của các lớp chung trong thư viện tiêu chuẩn để dễ dàng áp dụng type hints cho các lớp này.

Để triển khai các lớp chung tùy chỉnh có thể được tham số hóa trong thời gian chạy và được trình kiểm tra loại tĩnh hiểu, người dùng nên kế thừa từ một lớp thư viện tiêu chuẩn đã triển khai __class_getitem__() hoặc kế thừa từ typing.Generic, lớp này có cách triển khai __class_getitem__() riêng.

Việc triển khai tùy chỉnh __class_getitem__() trên các lớp được xác định bên ngoài thư viện tiêu chuẩn có thể không được các trình kiểm tra loại của bên thứ ba như mypy hiểu được. Không nên sử dụng __class_getitem__() trên bất kỳ lớp nào cho các mục đích khác ngoài gợi ý kiểu.

3.3.5.2. __class_getitem__ so với __getitem__

Thông thường, subscription của một đối tượng sử dụng dấu ngoặc vuông sẽ gọi phương thức cá thể __getitem__() được xác định trên lớp của đối tượng. Tuy nhiên, nếu đối tượng được đăng ký chính là một lớp thì phương thức lớp __class_getitem__() có thể được gọi thay thế. __class_getitem__() sẽ trả về một đối tượng GenericAlias nếu nó được xác định đúng.

Được trình bày cùng với expression obj[x], trình thông dịch Python tuân theo quy trình giống như sau để quyết định xem nên gọi __getitem__() hay __class_getitem__():

từ kiểm tra nhập khẩu isclass

đăng  def (obj, x):
    """Trả về kết quả của biểu thức 'obj[x]'"""

    class_of_obj = loại(obj)

    # If lớp obj định nghĩa __getitem__,
    # call class_of_obj.__getitem__(obj, x)
    nếu hasattr(class_of_obj, '__getitem__'):
        trả về class_of_obj.__getitem__(obj, x)

    # Else, nếu obj là một lớp và định nghĩa __class_getitem__,
    # call obj.__class_getitem__(x)
    elif isclass(obj)  hasattr(obj, '__class_getitem__'):
        trả về obj.__class_getitem__(x)

    # Else, đưa ra một ngoại lệ
    khác:
        nâng cao TypeError(
            Đối tượng f"'{class_of_obj.__name__}' không thể đăng ký được"
        )

Trong Python, tất cả các lớp đều là phiên bản của các lớp khác. Lớp của một lớp được gọi là metaclass của lớp đó và hầu hết các lớp đều có lớp type làm siêu dữ liệu của chúng. type không định nghĩa __getitem__(), nghĩa là các biểu thức như list[int], dict[str, float]tuple[str, bytes] đều dẫn đến __class_getitem__() được gọi:

>>> # list có "loại" lớp làm siêu dữ liệu của nó, giống như hầu hết các lớp:
>>> loại (danh sách)
<lớp 'loại'>
>>> loại(dict) == loại(danh sách) == loại(tuple) == loại(str) == loại(byte)
đúng
>>> # "list[int]" gọi "list.__class_getitem__(int)"
>>> danh sách[int]
danh sách[int]
>>> # list.__class_getitem__ trả về một đối tượng GenericAlias:
>>> loại(danh sách[int])
<class 'types.GenericAlias'>

Tuy nhiên, nếu một lớp có siêu dữ liệu tùy chỉnh xác định __getitem__(), việc đăng ký lớp đó có thể dẫn đến hành vi khác. Bạn có thể tìm thấy ví dụ về điều này trong mô-đun enum:

>>> từ nhập enum Enum
>>> Menu lớp(Enum):
... """Thực đơn bữa sáng"""
... SPAM = 'thư rác'
... BACON = 'thịt xông khói'
...
>>> Các lớp # Enum có siêu dữ liệu tùy chỉnh:
>>> loại(Thực đơn)
<lớp 'enum.EnumMeta'>
>>> # EnumMeta định nghĩa __getitem__,
>>> # so __class_getitem__ không được gọi,
>>> # and kết quả không phải là đối tượng GenericAlias:
>>> Thực đơn['SPAM']
<Menu.SPAM: 'thư rác'>
>>> (Menu['SPAM'])
<enum 'Thực đơn'>

Xem thêm

PEP 560 - Hỗ trợ cốt lõi cho việc gõ mô-đun và các loại chung

Giới thiệu __class_getitem__() và nêu rõ thời điểm subscription dẫn đến __class_getitem__() được gọi thay vì __getitem__()

3.3.6. Mô phỏng các đối tượng có thể gọi được

object.__call__(self[, args...])

Được gọi khi phiên bản được "gọi" dưới dạng hàm; nếu phương thức này được xác định, x(arg1, arg2, ...) tạm dịch là type(x).__call__(x, arg1, ...). Bản thân lớp object không cung cấp phương thức này.

3.3.7. Mô phỏng các loại container

Các phương thức sau đây có thể được định nghĩa để triển khai các đối tượng vùng chứa. Không ai trong số chúng được cung cấp bởi chính lớp object. Các vùng chứa thường là sequences (chẳng hạn như lists hoặc tuples) hoặc mappings (như dictionaries), nhưng cũng có thể đại diện cho các vùng chứa khác. Tập hợp các phương thức đầu tiên được sử dụng để mô phỏng một chuỗi hoặc để mô phỏng một ánh xạ; sự khác biệt là đối với một chuỗi, các khóa được phép phải là số nguyên k0 <= k < N trong đó N là độ dài của chuỗi hoặc đối tượng slice, xác định một phạm vi mục. Chúng tôi cũng khuyên rằng các ánh xạ nên cung cấp các phương thức keys(), values(), items(), get(), clear(), setdefault(), pop(), popitem(), copy()update() hoạt động tương tự như các phương thức dành cho các đối tượng dictionary tiêu chuẩn của Python. Mô-đun collections.abc cung cấp MutableMapping abstract base class để giúp tạo các phương thức đó từ bộ cơ sở gồm __getitem__(), __setitem__(), __delitem__()keys().

Các chuỗi có thể thay đổi sẽ cung cấp các phương thức append(), clear(), count(), extend(), index(), insert(), pop(), remove()reverse(), giống như các đối tượng list tiêu chuẩn của Python. Cuối cùng, các loại trình tự nên triển khai phép cộng (nghĩa là nối) và phép nhân (nghĩa là lặp lại) bằng cách xác định các phương thức __add__(), __radd__(), __iadd__(), __mul__(), __rmul__()__imul__() được mô tả bên dưới; họ không nên định nghĩa các toán tử số khác.

Chúng tôi khuyến nghị rằng cả ánh xạ và trình tự đều nên triển khai phương pháp __contains__() để cho phép sử dụng hiệu quả toán tử in; để ánh xạ, in sẽ tìm kiếm các khóa của ánh xạ; đối với các chuỗi, nó sẽ tìm kiếm thông qua các giá trị. Chúng tôi khuyến nghị thêm rằng cả ánh xạ và trình tự đều nên triển khai phương pháp __iter__() để cho phép lặp lại hiệu quả thông qua vùng chứa; để ánh xạ, __iter__() sẽ lặp qua các phím của đối tượng; đối với các chuỗi, nó sẽ lặp qua các giá trị.

object.__len__(self)

Được gọi để triển khai chức năng tích hợp len(). Phải trả về độ dài của đối tượng, một số nguyên >= 0. Ngoài ra, một đối tượng không xác định phương thức __bool__() và có phương thức __len__() trả về 0 được coi là sai trong ngữ cảnh Boolean.

Trong CPython, độ dài được yêu cầu tối đa là sys.maxsize. Nếu độ dài lớn hơn sys.maxsize thì một số tính năng (chẳng hạn như len()) có thể tăng OverflowError. Để ngăn chặn việc tăng OverflowError bằng cách kiểm tra giá trị thực, đối tượng phải xác định phương thức __bool__().

object.__length_hint__(self)

Được gọi để triển khai operator.length_hint(). Nên trả về độ dài ước tính cho đối tượng (có thể lớn hơn hoặc nhỏ hơn độ dài thực tế). Độ dài phải là số nguyên >= 0. Giá trị trả về cũng có thể là NotImplemented, được xử lý giống như khi phương thức __length_hint__ hoàn toàn không tồn tại. Phương pháp này hoàn toàn là một sự tối ưu hóa và không bao giờ cần thiết cho tính chính xác.

Added in version 3.4.

object.__getitem__(self, subscript)

Được gọi để triển khai subscription, tức là self[subscript]. Xem Đăng ký và cắt lát để biết chi tiết về cú pháp.

Có hai loại đối tượng tích hợp hỗ trợ đăng ký qua __getitem__():

  • sequences, trong đó subscript (còn gọi là index) phải là số nguyên hoặc đối tượng slice. Xem sequence documentation để biết hành vi dự kiến, bao gồm việc xử lý các đối tượng slice và các chỉ số tiêu cực.

  • mappings, trong đó subscript còn được gọi là key. Xem mapping documentation để biết hành vi dự kiến.

Nếu subscript thuộc loại không phù hợp, __getitem__() sẽ tăng TypeError. Nếu subscript có giá trị không phù hợp, __getitem__() sẽ tăng LookupError hoặc một trong các lớp con của nó (IndexError cho chuỗi; KeyError cho ánh xạ).

Ghi chú

Việc cắt lát được xử lý bởi __getitem__(), __setitem__()__delitem__(). Một cuộc gọi như

a[1:2] = b

được dịch sang

a[lát(1, 2, Không )] = b

vân vân. Các phần tử bị thiếu luôn được điền bằng None.

Ghi chú

Giao thức lặp trình tự (ví dụ: được sử dụng trong các vòng lặp for), hy vọng rằng IndexError sẽ được nâng lên đối với các chỉ mục không hợp lệ để cho phép phát hiện chính xác phần cuối của chuỗi.

Ghi chú

Khi subscripting a class, phương thức lớp đặc biệt __class_getitem__() có thể được gọi thay vì __getitem__(). Xem __class_getitem__ so với __getitem__ để biết thêm chi tiết.

object.__setitem__(self, key, value)

Được gọi để thực hiện gán cho self[key]. Lưu ý tương tự như đối với __getitem__(). Điều này chỉ nên được triển khai cho ánh xạ nếu đối tượng hỗ trợ thay đổi giá trị cho khóa hoặc nếu có thể thêm khóa mới hoặc cho chuỗi nếu các phần tử có thể được thay thế. Các ngoại lệ tương tự sẽ được đưa ra đối với các giá trị key không đúng như đối với phương pháp __getitem__().

object.__delitem__(self, key)

Được gọi để thực hiện xóa self[key]. Lưu ý tương tự như đối với __getitem__(). Điều này chỉ nên được triển khai cho ánh xạ nếu đối tượng hỗ trợ loại bỏ khóa hoặc cho chuỗi nếu các phần tử có thể bị xóa khỏi chuỗi. Các ngoại lệ tương tự sẽ được đưa ra đối với các giá trị key không đúng như đối với phương pháp __getitem__().

object.__missing__(self, key)

Được gọi bởi dict.__getitem__() để triển khai self[key] cho các lớp con dict khi khóa không có trong từ điển.

object.__iter__(self)

Phương thức này được gọi khi cần có iterator cho vùng chứa. Phương thức này sẽ trả về một đối tượng lặp mới có thể lặp qua tất cả các đối tượng trong vùng chứa. Để ánh xạ, nó sẽ lặp lại các khóa của vùng chứa.

object.__reversed__(self)

Được gọi (nếu có) bởi reversed() tích hợp để thực hiện phép lặp ngược. Nó sẽ trả về một đối tượng lặp mới lặp lại tất cả các đối tượng trong vùng chứa theo thứ tự ngược lại.

Nếu phương thức __reversed__() không được cung cấp, reversed() tích hợp sẽ quay lại sử dụng giao thức trình tự (__len__()__getitem__()). Các đối tượng hỗ trợ giao thức trình tự chỉ nên cung cấp __reversed__() nếu chúng có thể cung cấp cách triển khai hiệu quả hơn giao thức do reversed() cung cấp.

Các toán tử kiểm tra tư cách thành viên (innot in) thường được triển khai dưới dạng lặp qua một vùng chứa. Tuy nhiên, các đối tượng vùng chứa có thể cung cấp phương thức đặc biệt sau đây với cách triển khai hiệu quả hơn, điều này cũng không yêu cầu đối tượng phải lặp lại.

object.__contains__(self, item)

Được kêu gọi thực hiện các toán tử thử nghiệm thành viên. Sẽ trả về true nếu item nằm trong self, ngược lại là false. Đối với các đối tượng ánh xạ, điều này nên xem xét các khóa của ánh xạ thay vì các giá trị hoặc cặp mục khóa.

Đối với các đối tượng không xác định __contains__(), kiểm tra tư cách thành viên trước tiên sẽ thử lặp qua __iter__(), sau đó thử giao thức lặp trình tự cũ qua __getitem__(), xem this section in the language reference.

3.3.8. Mô phỏng các loại số

Các phương pháp sau đây có thể được định nghĩa để mô phỏng các đối tượng số. Các phương thức tương ứng với các phép toán không được hỗ trợ bởi loại số cụ thể được triển khai (ví dụ: các phép toán theo bit cho các số không nguyên) sẽ không được xác định.

object.__add__(self, other)
object.__sub__(self, other)
object.__mul__(self, other)
object.__matmul__(self, other)
object.__truediv__(self, other)
object.__floordiv__(self, other)
object.__mod__(self, other)
object.__divmod__(self, other)
object.__pow__(self, other[, modulo])
object.__lshift__(self, other)
object.__rshift__(self, other)
object.__and__(self, other)
object.__xor__(self, other)
object.__or__(self, other)

Các phương thức này được gọi để thực hiện các phép toán số học nhị phân (+, -, *, @, /, //, %, divmod(), pow(), **, <<, >>, &, ^, |). Ví dụ: để đánh giá biểu thức x + y, trong đó x là một phiên bản của lớp có phương thức __add__(), type(x).__add__(x, y) sẽ được gọi. Phương thức __divmod__() phải tương đương với việc sử dụng __floordiv__()__mod__(); nó không nên liên quan đến __truediv__(). Lưu ý rằng __pow__() phải được xác định để chấp nhận đối số thứ ba tùy chọn nếu phiên bản ba đối số của hàm pow() tích hợp được hỗ trợ.

Nếu một trong những phương thức đó không hỗ trợ thao tác với các đối số được cung cấp thì nó sẽ trả về NotImplemented.

object.__radd__(self, other)
object.__rsub__(self, other)
object.__rmul__(self, other)
object.__rmatmul__(self, other)
object.__rtruediv__(self, other)
object.__rfloordiv__(self, other)
object.__rmod__(self, other)
object.__rdivmod__(self, other)
object.__rpow__(self, other[, modulo])
object.__rlshift__(self, other)
object.__rrshift__(self, other)
object.__rand__(self, other)
object.__rxor__(self, other)
object.__ror__(self, other)

Các phương thức này được gọi để thực hiện các phép toán số học nhị phân (+, -, *, @, /, //, %, divmod(), pow(), **, <<, >>, &, ^, |) với phản xạ (hoán đổi) toán hạng. Các hàm này chỉ được gọi nếu toán hạng có kiểu khác nhau, khi toán hạng bên trái không hỗ trợ phép toán tương ứng [3], hoặc lớp của toán hạng bên phải được dẫn xuất từ ​​lớp của toán hạng bên trái. [4] Ví dụ: để đánh giá biểu thức x - y, trong đó y là một phiên bản của lớp có phương thức __rsub__(), type(y).__rsub__(y, x) được gọi nếu type(x).__sub__(x, y) trả về NotImplemented hoặc type(y) là lớp con của type(x). [5]

Lưu ý rằng __rpow__() phải được xác định để chấp nhận đối số thứ ba tùy chọn nếu phiên bản ba đối số của hàm pow() tích hợp được hỗ trợ.

Thay đổi trong phiên bản 3.14: pow() ba đối số bây giờ hãy thử gọi __rpow__() nếu cần. Trước đây nó chỉ được gọi trong pow() hai đối số và toán tử lũy thừa nhị phân.

Ghi chú

Nếu loại toán hạng bên phải là lớp con của loại toán hạng bên trái và lớp con đó cung cấp cách triển khai khác của phương thức được phản ánh cho thao tác, thì phương thức này sẽ được gọi trước phương thức không được phản ánh của toán hạng bên trái. Hành vi này cho phép các lớp con ghi đè hoạt động của tổ tiên chúng.

object.__iadd__(self, other)
object.__isub__(self, other)
object.__imul__(self, other)
object.__imatmul__(self, other)
object.__itruediv__(self, other)
object.__ifloordiv__(self, other)
object.__imod__(self, other)
object.__ipow__(self, other[, modulo])
object.__ilshift__(self, other)
object.__irshift__(self, other)
object.__iand__(self, other)
object.__ixor__(self, other)
object.__ior__(self, other)

Các phương thức này được gọi để thực hiện các phép gán số học tăng cường (+=, -=, *=, @=, /=, //=, %=, **=, <<=, >>=, &=, ^=, |=). Các phương thức này sẽ cố gắng thực hiện thao tác tại chỗ (sửa đổi self) và trả về kết quả (có thể là, nhưng không nhất thiết phải là self). Nếu một phương thức cụ thể không được xác định hoặc nếu phương thức đó trả về NotImplemented thì phép gán tăng cường sẽ quay trở lại các phương thức thông thường. Chẳng hạn, nếu x là một phiên bản của một lớp có phương thức __iadd__(), thì x += y tương đương với x = x.__iadd__(y) . Nếu __iadd__() không tồn tại hoặc nếu x.__iadd__(y) trả về NotImplemented, thì x.__add__(y)y.__radd__(x) sẽ được xem xét, như khi đánh giá x + y. Trong một số trường hợp nhất định, phép gán tăng cường có thể dẫn đến các lỗi không mong muốn (xem Tại sao a_tuple[i] += ['item'] lại đưa ra ngoại lệ khi tính năng bổ sung hoạt động?), nhưng trên thực tế, hành vi này là một phần của mô hình dữ liệu.

object.__neg__(self)
object.__pos__(self)
object.__abs__(self)
object.__invert__(self)

Được gọi để thực hiện các phép toán số học đơn phân (-, +, abs()~).

object.__complex__(self)
object.__int__(self)
object.__float__(self)

Được gọi để triển khai các hàm dựng sẵn complex(), int()float(). Nên trả về một giá trị thuộc loại thích hợp.

object.__index__(self)

Được gọi để triển khai operator.index() và bất cứ khi nào Python cần chuyển đổi một cách dễ dàng đối tượng số thành đối tượng số nguyên (chẳng hạn như khi cắt hoặc trong các hàm bin(), hex()oct() tích hợp sẵn). Sự hiện diện của phương thức này chỉ ra rằng đối tượng số là một kiểu số nguyên. Phải trả về một số nguyên.

Nếu __int__(), __float__()__complex__() không được xác định thì các hàm tích hợp tương ứng int(), float()complex() sẽ quay trở lại __index__().

object.__round__(self[, ndigits])
object.__trunc__(self)
object.__floor__(self)
object.__ceil__(self)

Được gọi để triển khai hàm tích hợp round()math. Các hàm trunc(), floor()ceil(). Trừ khi ndigits được chuyển tới __round__(), tất cả các phương thức này sẽ trả về giá trị của đối tượng bị cắt bớt thành Integral (thường là int).

Thay đổi trong phiên bản 3.14: int() không còn ủy quyền cho phương thức __trunc__() nữa.

3.3.9. Với Trình quản lý bối cảnh câu lệnh

context manager là một đối tượng xác định bối cảnh thời gian chạy sẽ được thiết lập khi thực thi câu lệnh with. Trình quản lý bối cảnh xử lý việc nhập và thoát khỏi bối cảnh thời gian chạy mong muốn để thực thi khối mã. Trình quản lý bối cảnh thường được gọi bằng câu lệnh with (được mô tả trong phần Tuyên bố with), nhưng cũng có thể được sử dụng bằng cách gọi trực tiếp các phương thức của chúng.

Các ứng dụng điển hình của trình quản lý bối cảnh bao gồm lưu và khôi phục các loại trạng thái toàn cầu khác nhau, khóa và mở khóa tài nguyên, đóng các tệp đã mở, v.v.

Để biết thêm thông tin về trình quản lý bối cảnh, hãy xem Các loại trình quản lý bối cảnh. Bản thân lớp object không cung cấp các phương thức quản lý bối cảnh.

object.__enter__(self)

Nhập bối cảnh thời gian chạy liên quan đến đối tượng này. Câu lệnh with sẽ liên kết giá trị trả về của phương thức này với (các) mục tiêu được chỉ định trong mệnh đề as của câu lệnh, nếu có.

object.__exit__(self, exc_type, exc_value, traceback)

Thoát khỏi bối cảnh thời gian chạy liên quan đến đối tượng này. Các tham số mô tả ngoại lệ khiến ngữ cảnh bị thoát. Nếu ngữ cảnh được thoát mà không có ngoại lệ, cả ba đối số sẽ là None.

Nếu một ngoại lệ được cung cấp và phương thức muốn loại bỏ ngoại lệ đó (tức là ngăn chặn nó được lan truyền), thì nó sẽ trả về một giá trị thực. Nếu không, ngoại lệ sẽ được xử lý bình thường khi thoát khỏi phương thức này.

Lưu ý rằng các phương thức __exit__() không được lấy lại ngoại lệ đã truyền vào; đây là trách nhiệm của người gọi.

Xem thêm

PEP 343 - Câu lệnh "với"

Thông số kỹ thuật, nền tảng và ví dụ cho câu lệnh with của Python.

3.3.10. Tùy chỉnh các đối số vị trí trong khớp mẫu lớp

Khi sử dụng tên lớp trong một mẫu, theo mặc định, các đối số vị trí trong mẫu không được phép, tức là case MyClass(x, y) thường không hợp lệ nếu không có hỗ trợ đặc biệt trong MyClass. Để có thể sử dụng loại mẫu đó, lớp cần xác định thuộc tính __match_args__.

object.__match_args__

Biến lớp này có thể được gán một bộ chuỗi. Khi lớp này được sử dụng trong mẫu lớp có đối số vị trí, mỗi đối số vị trí sẽ được chuyển đổi thành đối số từ khóa, sử dụng giá trị tương ứng trong __match_args__ làm từ khóa. Việc thiếu thuộc tính này tương đương với việc đặt nó thành ().

Ví dụ: nếu MyClass.__match_args__("left", "center", "right") thì có nghĩa là case MyClass(x, y) tương đương với case MyClass(left=x, center=y). Lưu ý rằng số lượng đối số trong mẫu phải nhỏ hơn hoặc bằng số phần tử trong __match_args__; nếu nó lớn hơn, nỗ lực khớp mẫu sẽ tăng TypeError.

Added in version 3.10.

Xem thêm

PEP 634 - Khớp mẫu cấu trúc

Đặc tả cho câu lệnh match của Python.

3.3.11. Mô phỏng các loại bộ đệm

Zz000zz cung cấp một cách để các đối tượng Python có khả năng truy cập hiệu quả vào mảng bộ nhớ cấp thấp. Giao thức này được triển khai bởi các loại dựng sẵn như bytesmemoryview và các thư viện của bên thứ ba có thể xác định các loại bộ đệm bổ sung.

Mặc dù các loại bộ đệm thường được triển khai bằng C, nhưng cũng có thể triển khai giao thức bằng Python.

object.__buffer__(self, flags)

Được gọi khi bộ đệm được yêu cầu từ self (ví dụ: bởi hàm tạo memoryview). Đối số flags là một số nguyên biểu thị loại bộ đệm được yêu cầu, ví dụ như ảnh hưởng đến việc bộ đệm được trả về là chỉ đọc hay có thể ghi. inspect.BufferFlags cung cấp một cách thuận tiện để diễn giải các cờ. Phương thức này phải trả về một đối tượng memoryview.

Thread safety: Trong free-threaded Python, việc triển khai phải quản lý mọi bộ đếm xuất nội bộ bằng các hoạt động nguyên tử. Phương thức này phải an toàn để gọi đồng thời từ nhiều luồng và dữ liệu cơ bản của bộ đệm được trả về phải duy trì hiệu lực cho đến khi lệnh gọi __release_buffer__() tương ứng hoàn tất. Xem An toàn luồng cho các đối tượng MemoryView để biết chi tiết.

object.__release_buffer__(self, buffer)

Được gọi khi bộ đệm không còn cần thiết nữa. Đối số buffer là một đối tượng memoryview đã được trả về trước đó bởi __buffer__(). Phương thức này phải giải phóng mọi tài nguyên liên quan đến bộ đệm. Phương thức này sẽ trả về None.

Thread safety: Trong free-threaded Python, mọi sự giảm bộ đếm xuất đều phải sử dụng các phép toán nguyên tử. Việc dọn dẹp tài nguyên phải an toàn theo luồng, vì bản phát hành cuối cùng có thể chạy đua với các bản phát hành đồng thời từ các luồng khác.

Các đối tượng bộ đệm không cần thực hiện bất kỳ việc dọn dẹp nào đều không bắt buộc phải triển khai phương pháp này.

Added in version 3.12.

Xem thêm

PEP 688 - Làm cho giao thức bộ đệm có thể truy cập được bằng Python

Giới thiệu các phương thức Python __buffer____release_buffer__.

collections.abc.Buffer

ABC cho các loại bộ đệm.

3.3.12. Chú thích

Các hàm, lớp và mô-đun có thể chứa annotations, đây là một cách để liên kết thông tin (thường là type hints) với một ký hiệu.

object.__annotations__

Thuộc tính này chứa các chú thích cho một đối tượng. Đó là lazily evaluated, vì vậy việc truy cập vào thuộc tính có thể thực thi mã tùy ý và đưa ra các ngoại lệ. Nếu đánh giá thành công, thuộc tính sẽ được đặt thành ánh xạ từ điển từ tên biến đến chú thích.

Thay đổi trong phiên bản 3.14: Các chú thích bây giờ được đánh giá một cách lười biếng.

object.__annotate__(format)

Một annotate function. Trả về tên thuộc tính/tham số ánh xạ đối tượng từ điển mới cho các giá trị chú thích của chúng.

Lấy một tham số định dạng chỉ định định dạng mà các giá trị chú thích sẽ được cung cấp. Nó phải là thành viên của enum annotationlib.Format hoặc một số nguyên có giá trị tương ứng với thành viên của enum.

Nếu chức năng chú thích không hỗ trợ định dạng được yêu cầu thì nó phải tăng NotImplementedError. Các hàm chú thích phải luôn hỗ trợ định dạng VALUE; họ không được tăng NotImplementedError() khi được gọi với định dạng này.

Khi được gọi với định dạng VALUE, hàm chú thích có thể tăng NameError; nó không được tăng NameError khi được gọi yêu cầu bất kỳ định dạng nào khác.

Nếu một đối tượng không có bất kỳ chú thích nào, tốt nhất nên đặt __annotate__ thành None (không thể xóa nó), thay vì đặt thành một hàm trả về một lệnh trống.

Added in version 3.14.

Xem thêm

PEP 649 --- Đánh giá trì hoãn chú thích bằng cách sử dụng bộ mô tả

Giới thiệu tính năng đánh giá lười biếng các chú thích và hàm __annotate__.

3.3.13. Tra cứu phương pháp đặc biệt

Đối với các lớp tùy chỉnh, các lệnh gọi ngầm của các phương thức đặc biệt chỉ được đảm bảo hoạt động chính xác nếu được xác định trên loại đối tượng chứ không phải trong từ điển đối tượng của đối tượng. Hành vi đó là lý do tại sao đoạn mã sau đưa ra một ngoại lệ:

>>> lớp C:
... vượt qua
...
>>> c = C()
>>> c.__len__ = lambda: 5
>>> len(c)
Traceback (cuộc gọi gần đây nhất):
  Tệp "<stdin>", dòng 1, trong <module>
TypeError: đối tượng loại 'C' không có len()

Lý do đằng sau hành vi này nằm ở một số phương thức đặc biệt như __hash__()__repr__() được thực hiện bởi tất cả các đối tượng, bao gồm cả đối tượng kiểu. Nếu việc tra cứu ngầm của các phương thức này sử dụng quy trình tra cứu thông thường, thì chúng sẽ thất bại khi được gọi trên chính đối tượng kiểu đó:

>>> 1 .__hash__() == hàm băm(1)
đúng
>>> int.__hash__() == băm(int)
Traceback (cuộc gọi gần đây nhất):
  Tệp "<stdin>", dòng 1, trong <module>
TypeError: bộ mô tả '__hash__' của đối tượng 'int' cần một đối số

Việc cố gắng gọi không chính xác một phương thức không liên kết của một lớp theo cách này đôi khi được gọi là 'nhầm lẫn siêu dữ liệu' và có thể tránh được bằng cách bỏ qua thể hiện khi tra cứu các phương thức đặc biệt:

>>> (1).__hash__(1) == băm(1)
đúng
>>> (int).__hash__(int) == băm(int)
đúng

Ngoài việc bỏ qua bất kỳ thuộc tính phiên bản nào để đảm bảo tính chính xác, việc tra cứu phương thức đặc biệt tiềm ẩn nói chung cũng bỏ qua phương thức __getattribute__() ngay cả đối với siêu dữ liệu của đối tượng:

>>> lớp Meta(loại):
... def __getattribute__(*args):
... print("Siêu lớp getattribute được gọi")
... kiểu trả về.__getattribute__(*args)
...
>>> lớp C(đối tượng, metaclass=Meta):
... chắc chắn __len__(tự):
... trả về 10
... def __getattribute__(*args):
... print("Lớp getattribute được gọi")
... trả về đối tượng.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__() tra cứu # Explicit qua phiên bản
Lớp getattribute được gọi
10
>>> type(c).__len__(c) # Explicit tra cứu qua kiểu
Thuộc tính getattribute metaclass được gọi
10
>>> tra cứu len(c) # Implicit
10

Việc bỏ qua máy __getattribute__() theo cách này cung cấp phạm vi đáng kể cho việc tối ưu hóa tốc độ trong trình thông dịch, với cái giá là phải linh hoạt trong việc xử lý các phương thức đặc biệt (phương thức đặc biệt must được đặt trên chính đối tượng lớp để được trình thông dịch gọi một cách nhất quán).

3.4. Coroutine

3.4.1. Đối tượng chờ đợi

Đối tượng awaitable thường triển khai phương thức __await__(). Coroutine objects được trả về từ các hàm async def có thể chờ được.

Ghi chú

Các đối tượng generator iterator được trả về từ các trình tạo được trang trí bằng types.coroutine() cũng có thể được chờ đợi, nhưng chúng không triển khai __await__().

object.__await__(self)

Phải trả lại iterator. Nên được sử dụng để triển khai các đối tượng awaitable. Ví dụ: asyncio.Future triển khai phương thức này để tương thích với biểu thức await. Bản thân lớp object không thể chờ đợi được và không cung cấp phương thức này.

Ghi chú

Ngôn ngữ này không đặt ra bất kỳ hạn chế nào về loại hoặc giá trị của các đối tượng do trình lặp được trả về bởi __await__, vì điều này dành riêng cho việc triển khai khung thực thi không đồng bộ (ví dụ: asyncio) sẽ quản lý đối tượng awaitable.

Added in version 3.5.

Xem thêm

PEP 492 để biết thêm thông tin về các đối tượng có thể chờ đợi.

3.4.2. Đối tượng Coroutine

Coroutine objects là các đối tượng awaitable. Việc thực thi coroutine có thể được kiểm soát bằng cách gọi __await__() và lặp lại kết quả. Khi coroutine thực thi xong và trả về, iterator sẽ tăng StopIteration và thuộc tính value của ngoại lệ giữ giá trị trả về. Nếu coroutine đưa ra một ngoại lệ, nó sẽ được truyền bởi iterator. Coroutine không được trực tiếp đưa ra các ngoại lệ StopIteration chưa được xử lý.

Coroutine cũng có các phương thức được liệt kê bên dưới, tương tự như các phương thức của trình tạo (xem Phương pháp tạo-lặp). Tuy nhiên, không giống như các trình tạo, coroutine không hỗ trợ trực tiếp việc lặp.

Thay đổi trong phiên bản 3.5.2: Đó là một RuntimeError chờ đợi trên một coroutine nhiều lần.

coroutine.send(value)

Bắt đầu hoặc tiếp tục thực thi coroutine. Nếu valueNone, điều này tương đương với việc nâng cao trình lặp được trả về bởi __await__(). Nếu value không phải là None, thì phương thức này ủy quyền cho phương thức send() của iterator đã khiến coroutine tạm dừng. Kết quả (giá trị trả về, StopIteration hoặc ngoại lệ khác) giống như khi lặp qua giá trị trả về __await__(), được mô tả ở trên.

coroutine.throw(value)
coroutine.throw(type[, value[, traceback]])

Tăng ngoại lệ được chỉ định trong coroutine. Phương thức này ủy quyền cho phương thức throw() của trình vòng lặp đã khiến coroutine tạm dừng, nếu nó có phương thức như vậy. Nếu không, ngoại lệ sẽ được đưa ra tại điểm tạm dừng. Kết quả (giá trị trả về, StopIteration hoặc ngoại lệ khác) giống như khi lặp qua giá trị trả về __await__(), được mô tả ở trên. Nếu ngoại lệ không được ghi lại trong coroutine, nó sẽ truyền trở lại người gọi.

Thay đổi trong phiên bản 3.12: Chữ ký thứ hai (type[, value[, traceback]]) không được dùng nữa và có thể bị xóa trong phiên bản Python trong tương lai.

coroutine.close()

Làm cho coroutine tự dọn dẹp và thoát ra. Nếu coroutine bị tạm dừng, trước tiên, phương thức này sẽ ủy quyền cho phương thức close() của trình vòng lặp khiến coroutine bị tạm dừng, nếu nó có phương thức như vậy. Sau đó, nó tăng GeneratorExit tại điểm treo, khiến coroutine tự dọn sạch ngay lập tức. Cuối cùng, coroutine được đánh dấu là đã thực thi xong, ngay cả khi nó chưa bao giờ được bắt đầu.

Các đối tượng Coroutine sẽ tự động được đóng bằng quy trình trên khi chúng sắp bị phá hủy.

3.4.3. Trình lặp không đồng bộ

Một asynchronous iterator có thể gọi mã không đồng bộ trong phương thức __anext__ của nó.

Các trình vòng lặp không đồng bộ có thể được sử dụng trong câu lệnh async for.

Bản thân lớp object không cung cấp các phương thức này.

object.__aiter__(self)

Phải trả về một đối tượng asynchronous iterator.

object.__anext__(self)

Phải trả về awaitable dẫn đến giá trị tiếp theo của trình vòng lặp. Sẽ xuất hiện lỗi StopAsyncIteration khi quá trình lặp kết thúc.

Một ví dụ về đối tượng lặp không đồng bộ:

Trình đọc lớp:
    dòng đọc không đồng bộ (tự):
        ...

    chắc chắn __aiter__(tự):
        tự trở về

    async def __anext__(self):
        val = đang chờ self.readline()
        nếu giá trị == b'':
            nâng cao StopAsyncIteration
        giá trị trả lại

Added in version 3.5.

Thay đổi trong phiên bản 3.7: Trước Python 3.7, __aiter__() có thể trả về awaitable sẽ phân giải thành asynchronous iterator.

Bắt đầu với Python 3.7, __aiter__() phải trả về một đối tượng trình vòng lặp không đồng bộ. Trả lại bất cứ thứ gì khác sẽ dẫn đến lỗi TypeError.

3.4.4. Trình quản lý bối cảnh không đồng bộ

Một asynchronous context manager là một context manager có thể tạm dừng thực thi trong các phương thức __aenter____aexit__ của nó.

Trình quản lý bối cảnh không đồng bộ có thể được sử dụng trong câu lệnh async with.

Bản thân lớp object không cung cấp các phương thức này.

object.__aenter__(self)

Về mặt ngữ nghĩa tương tự như __enter__(), điểm khác biệt duy nhất là nó phải trả về awaitable.

object.__aexit__(self, exc_type, exc_value, traceback)

Về mặt ngữ nghĩa tương tự như __exit__(), điểm khác biệt duy nhất là nó phải trả về awaitable.

Một ví dụ về lớp trình quản lý bối cảnh không đồng bộ

lớp AsyncContextManager:
    async def __aenter__(self):
        đang chờ nhật ('nhập ngữ cảnh')

    async def __aexit__(self, exc_type, exc, tb):
        đang chờ nhật  ('thoát bối cảnh')

Added in version 3.5.

Chú thích cuối trang