Các đối tượng 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 đối tượng hoặc bằng quan hệ giữa các đối tượng. [Theo một nghĩa nào đó, và phù hợp với mô hình “máy tính chương trình được lưu trữ” của Von Neumann, mã cũng được biểu diễn bằng các đối tượng. ]
Mỗi đối tượng có một danh tính, một loại và một giá trị. Danh tính của một đối tượng không bao giờ thay đổi khi nó đã được tạo; . Toán tử ‘’ so sánh danh tính của hai đối tượng;
Chi tiết triển khai CPython. Đối với CPython,
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule9 là địa chỉ bộ nhớ lưu trữ
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass0
Loại đối tượng xác định các hoạt động mà đối tượng hỗ trợ [e. g. , "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 trả về kiểu của một đối tượng [chính nó là một đối tượng]. Giống như danh tính của nó, loại đối tượng cũng không thể thay đổi.
Giá trị 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à có thể thay đổi; . [Giá trị của một đối tượng vùng chứa bất biến có 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 này bị thay đổi; tuy nhiên, vùng chứa vẫn được coi là bất biến, bởi 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 với việc có một giá trị không thể thay đổi, nó tinh tế hơn. ] Khả năng thay đổi của một đối tượng được xác định bởi loại của nó;
Các đối tượng không bao giờ bị phá hủy một cách rõ ràng; . Việc triển khai được phép hoãn việc thu gom rác hoặc bỏ qua hoàn toàn — đó là vấn đề về chất lượng triển khai, cách thức 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
Chi tiết triển khai CPython. CPython hiện đang sử dụng sơ đồ đếm tham chiếu với [tùy chọn] phát hiện chậm rác được liên kết theo chu kỳ, 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 được đảm bảo để thu thập rác chứa tham chiếu vòng tròn. Xem tài liệu của mô-đun để biết thông tin về cách kiểm soát việc thu gom rác tuần hoàn. Các triển khai khác hoạt động khác và CPython có thể thay đổi. Khô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 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 triển khai có thể giữ cho các đối tượng 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 một ngoại lệ bằng câu lệnh '…' có thể giữ cho các đối tượng tồn tại
Một số đối tượng chứa các tham chiếu đến tài nguyên “bên ngoài” chẳng hạn như 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 được đảm bảo 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
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass5. Các chương trình được khuyến khích mạnh mẽ để đóng các đối tượng như vậy một cách rõ ràng. Câu lệnh ‘…’ và câu lệnh ‘’ cung cấp các 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; . Ví dụ về vù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 một vùng chứa, chúng ta ngụ ý các giá trị, không phải danh tính của các đối tượng được chứa; . Vì vậy, nếu một bộ 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 danh tính đối tượng cũng bị ảnh hưởng theo một nghĩa nào đó. đối với các loại bất biến, 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. E. g. , after
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass9,
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']0 and
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']1 may or may not refer to the same object with the value one, depending on the implementation, but after
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']2,
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']3 and
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']4 are guaranteed to refer to two different, unique, newly created empty lists. [Lưu ý rằng
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']5 gán cùng một đối tượng cho cả
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']3 và
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']4. ]
3. 2. The standard type hierarchy
Dưới đây là danh sách các loại được tích hợp sẵn 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 việc 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 loại vào hệ thống phân cấp loại [e. g. , rational numbers, efficiently stored arrays of integers, etc. ], mặc dù những phần bổ sung như vậy thường sẽ được cung cấp thông qua thư viện chuẩn để thay thế
Một số mô tả loại bên dưới chứa đoạn liệt kê 'thuộc tính đặc biệt. ’ These are attributes that provide access to the implementation and are not intended for general use. Định nghĩa của họ có thể thay đổi trong tương lai
Không cóLoại này có một giá trị duy nhất. Có một đối tượng duy nhất với giá trị này. Đối tượng này được truy cập thông qua tên dựng sẵn
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8. Nó được sử dụng để biểu thị sự vắng mặt của một giá trị trong nhiều tình huống, e. g. , nó được trả về từ các hàm không trả về bất cứ thứ gì một cách rõ ràng. Giá trị thật của nó là saiKhông được 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 với giá trị này. This object is accessed through the built-in name
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']9. Numeric methods and rich comparison methods should return this value if they do not implement the operation for the operands provided. [Trình thông dịch sau đó sẽ thử thao tác được phản ánh hoặc một số hoạt động dự phòng khác, tùy thuộc vào người vận hành. ] Nó không nên được đánh giá trong ngữ cảnh boolean
See for more details
Changed in version 3. 9. Đánh giá
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']9 trong ngữ cảnh boolean không được dùng nữa. Mặc dù nó hiện được đánh giá là đúng, nhưng nó sẽ phát ra một. Nó sẽ nâng cao trong phiên bản tương lai của Python. dấu chấm lửng
Loại này có một giá trị duy nhất. Có một đối tượng duy nhất với giá trị này. Đối tượng này được truy cập thông qua tên viết tắt
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook3 hoặc tên tích hợp sẵn
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook4. Giá trị thật của nó là true
Chúng được tạo bởi các chữ 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 tích hợp số học. Các đối tượng số là bất biến; . Tất nhiên, các số trong Python có liên quan chặt chẽ với các số toán học, nhưng chịu các hạn chế của biểu diễn số trong máy tính
Các biểu diễn chuỗi của các lớp số, được tính bởi và , có các thuộc tính sau
Chúng là các chữ số hợp lệ, khi được chuyển đến hàm tạo của lớp chúng, sẽ tạo ra một đối tượng có giá trị của số ban đầu
Biểu diễn ở cơ sở 10, khi có thể
Các số 0 ở đầu, có thể ngoại trừ một số 0 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 sau dấu thập phân, không được hiển thị
Một dấu hiệ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
Chúng đại diện cho các phần tử từ tập hợp các số nguyên [dương và âm]
Có hai loại số nguyên
Số nguyên []Chúng đại diện cho các số trong một 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ạ, một biểu diễn nhị phân được giả định và các số âm được biểu diễn dưới dạng một biến thể của phần bù 2, điều này tạo ảo giác về một chuỗi vô hạn các bit dấu kéo dài sang trái
Boolean []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ị
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass1 và
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass2 là các đối tượng Boolean duy nhất. Kiểu Boolean là một kiểu con của kiểu 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
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass3 hoặc
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass4 được trả về tương ứng
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ề phép dịch chuyển và mặt nạ liên quan đến số nguyên âm
[]Chúng đại diện cho các số dấu phẩy động chính xác kép ở cấp độ máy. Bạn phụ thuộc vào kiến trúc máy bên dưới [và triển khai C hoặc Java] cho phạm vi được chấp nhận và xử lý tràn. Python không hỗ trợ các số dấu phẩy động có độ chính xác đơn;
[]Chúng biểu thị các số phức dưới dạng một cặp số dấu phẩy động chính xác kép ở cấp độ máy. Các cảnh báo tương tự áp dụng cho các số dấu phẩy động. Phần thực và phần ảo của một số phức
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass9 có thể được truy xuất thông qua các thuộc tính chỉ đọc
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]0 và
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]1trì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 trả về số lượng phần tử của một chuỗi. Khi độ dài của một dãy là n, bộ chỉ số chứa các số 0, 1, …, n-1. Mục i của chuỗi a được chọn bởi
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]3
Trình tự cũng hỗ trợ cắt.
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]4 chọn tất cả các mục có chỉ số k sao cho i
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]5 k
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]6 j. Khi được sử dụng như một biểu thức, một lát cắt là một chuỗi cùng loại. Điều này ngụ ý rằng bộ chỉ mục được đánh số lại để nó bắt đầu từ 0
Một số trình tự cũng hỗ trợ “cắt lát mở rộng” với tham số “bước” thứ ba.
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]7 chọn tất cả các mục của a có chỉ số x trong đó
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]8, n
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]9
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]0 và i
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]5 x
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]6 j
Các trình tự được phân biệt theo khả năng biến đổi của chúng
Trình tự bất biếnMột đối tượng thuộc loại chuỗi bất biến không thể thay đổi sau khi đượ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ể 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 không thể thay đổi không thể thay đổi. ]
Các loại sau đây là trình tự bất biến
DâyChuỗi là một chuỗi các giá trị đại diện cho các điểm mã Unicode. Tất cả các điểm mã trong phạm vi
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]3 có thể được biểu diễn trong một chuỗi. Python không có loại char ; . Hàm tích hợp chuyển đổi một điểm mã từ dạng chuỗi của nó thành một số nguyên trong phạm vi
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]6; . có thể được sử dụng để chuyển đổi sang sử dụng mã hóa văn bản đã cho và có thể được sử dụng để đạt được điều ngược lại. bộ dữ liệu
Các mục của một tuple là các đối tượng Python tùy ý. Các bộ gồm hai mục trở lên được tạo bởi các danh sách biểu thức được phân tách bằng dấu phẩy. Một bộ của một mục [một 'singleton'] có thể được tạo bằng cách thêm 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ì dấu ngoặc đơn phải được sử dụng để nhóm các biểu thức]. Một bộ trống có thể được tạo bởi một cặp dấu ngoặc đơn rỗng
byteMột đối tượng bytes là một mảng bất biến. Các mục là các byte 8 bit, được biểu thị bằng các số nguyên trong phạm vi 0 >> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']] 4] và hàm tạo 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
trình tự có thể thay đổiTrì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à [xóa]
Hiện tại có hai loại trình tự có thể thay đổi nội tại
danh sáchCá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 mộ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ó trường hợp đặc biệt nào cần thiết để tạo danh sách có độ dài 0 hoặc 1. ]
Mảng byteMột đối tượng bytearray là một mảng có thể thay đổi. Chúng được tạo bởi hàm tạo tích hợp. Ngoài việc có thể thay đổi [và do đó không thể băm được], các mảng byte còn cung cấp giao diện và chức năng giống như các đối tượng bất biến
Mô-đun mở rộng cung cấp một ví dụ bổ sung về loại trình tự có thể thay đổi, cũng như mô-đun
Đặt loạiChú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ố nào. Tuy nhiên, chúng có thể được lặp đi lặp lại và hàm tích hợp trả về số lượng mục trong một tập hợp. Các cách sử dụng phổ biến cho các tập hợp là kiểm tra tư cách thành viên nhanh, loại bỏ các bản trùng lặp khỏi một chuỗi và tính toán các phép toán như giao, hợp, hiệu và hiệu đố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ự áp dụng cho các khóa từ điển. Note that numeric types obey the normal rules for numeric comparison. nếu hai số so sánh bằng nhau [e. g. ,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]4 và
a[1:2] = b4], chỉ một trong số chúng có thể được chứa trong một bộ
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 dựng sẵn và có thể được sửa đổi sau đó bằng một số phương thức, chẳng hạn như
a[1:2] = b6Frozen sets
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 tích hợp. As a frozenset is immutable and , it can be used again as an element of another set, or as a dictionary key
ánh xạChúng đại diện cho các bộ đối tượng hữu hạn được lập chỉ mục bởi các bộ chỉ mục tùy ý. Ký hiệu chỉ số phụ
a[1:2] = b8 chọn mục được lập chỉ mục bởi
a[1:2] = b9 từ ánh xạ
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']0; . Hàm tích hợp 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
từ điểnChúng đại diện cho các bộ đối tượng hữu hạn đượ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 loại số được sử dụng cho các phím 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 [e. g. ,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]4 và
a[1:2] = b4] 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 duy trì 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. Thay thế một khóa hiện có không thay đổi thứ tự, tuy nhiên việc xóa một khóa và cắm 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ác mô-đun mở rộng và cung cấp các ví dụ bổ sung về các loại ánh xạ, cũng như mô-đun
Đã 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 được giữ nguyên, nhưng nó được coi là chi tiết triển khai tại thời điểm đó hơn là đảm bảo ngôn ngữ.
các loại có thể gọiĐây là những loại có thể áp dụng thao tác gọi hàm [xem phần ]
Hàm do người dùng định nghĩaMột đối tượng hàm do người dùng định nghĩa được tạo bởi một định nghĩa hàm [xem phần ]. Nó nên đượ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
thuộc tính đặc biệt
Thuộc tính
Nghĩa
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule09
Chuỗi tài liệu của chức năng, hoặc
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8 nếu không có;
Có thể ghi
Tên chức năng
Có thể ghi
Chức năng
Mới trong phiên bản 3. 3
Có thể ghi
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule13
Tên của mô-đun mà chức năng đã được xác định trong hoặc
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8 nếu không có
Có thể ghi
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule15
Một bộ chứa các giá trị đối số mặc định cho những đối số có giá trị mặc định hoặc
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8 nếu không có đối số nào có giá trị mặc định
Có thể ghi
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule17
Đối tượng mã đại diện cho thân hàm đã biên dịch
Có thể ghi
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule18
Tham chiếu đến từ điển chứa các biến toàn cục của hàm — không gian tên toàn cục của mô-đun trong đó hàm được xác định
Chỉ đọc
Không gian tên hỗ trợ các thuộc tính chức năng tùy ý
Có thể ghi
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule20
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8 hoặc một bộ ô chứa các liên kết cho các biến tự do của hàm. Xem bên dưới để biết thông tin về thuộc tính
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule22
Chỉ đọc
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule23
Một dict chứa chú thích của các tham số. Các khóa của dict là tên tham số và
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule24 cho chú thích trả về, nếu được cung cấp. Để biết thêm thông tin về cách làm việc với thuộc tính này, hãy xem
Có thể ghi
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule25
Một lệnh chứa các giá trị mặc định cho các tham số chỉ từ khóa
Có thể ghi
Hầu hết các thuộc tính có nhãn “Writable” kiểm tra loại giá trị được gán
Các đối tượng hàm cũng hỗ trợ nhận và đặt 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 đó. Lưu ý rằng việc triển khai hiện tại chỉ hỗ trợ các thuộc tính chức năng trên các chức năng do người dùng xác định. Các thuộc tính chức năng trên các chức năng tích hợp có thể được hỗ trợ trong tương lai
Một đối tượng ô có thuộc tính
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule22. Điều này có thể được sử dụng để lấy giá trị của ô, cũng như đặt giá trị
Thông tin bổ sung về định nghĩa của hàm có thể được truy xuất từ đối tượng mã của nó; . Loại có thể được truy cập trong mô-đun
Phương thức sơ thẩmMột đối tượng phương thức thể hiện kết hợp một lớp, một thể hiện của lớp và bất kỳ đối tượng nào có thể gọi được [thông thường là một hàm do người dùng định nghĩa]
Thuộc tính chỉ đọc đặc biệt.
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule29 là đối tượng thể hiện của lớp,
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule30 là đối tượng hàm;
Các phương thức cũng hỗ trợ truy cập [nhưng không cài đặt] các thuộc tính hàm tùy ý trên đối tượng hàm bên dưới
Các đối tượng phương thức do người dùng định nghĩa có thể được tạo khi nhận 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à một đối tượng hàm do người dùng định nghĩa hoặc một đối tượng phương thức của lớp
Khi một đối tượng phương thức thể hiện được tạo bằng cách truy xuất một đối tượng hàm do người dùng định nghĩa từ một lớp thông qua một trong các thể hiện của nó, thì thuộc tính
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule29 của nó là thể hiện và đối tượng phương thức được cho là bị ràng buộc. Thuộc tính
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule30 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 thể hiện được tạo bằng cách truy xuất một đối tượng phương thức lớp từ một lớp hoặc một thể hiện, thuộc tính
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule29 của nó là chính lớp đó và thuộc tính
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule30 của nó là đối tượng hàm bên dưới phương thức lớp
Khi một đối tượng phương thức thể hiện được gọi, hàm bên dưới [
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule30] được gọi, chèn thể hiện của lớp [
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule29] trước danh sách đối số. Chẳng hạn, khi
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule43 là một lớp chứa định nghĩa cho một hàm
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule44 và
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass0 là một thể hiện của
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule43, việc gọi
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule47 tương đương với việc gọi
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule48
Khi một đối tượng phương thức thể hiện được bắt nguồn từ một đối tượng phương thức lớp, thì “thể hiện lớp” được lưu trữ trong
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule29 sẽ thực sự là chính lớp đó, do đó, việc gọi
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule47 hoặc
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule51 tương đương với việc gọi
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule52 trong đó
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule53 là hàm cơ bản
Lưu ý rằng việc chuyển đổi từ đối tượng hàm sang đối tượng phương thức thể hiện xảy ra mỗi khi thuộc tính được truy xuất từ thể hiện. Trong một số trường hợp, cách tối ưu hiệu quả là gán thuộc tính cho một biến cục bộ và gọi biến cục bộ đó. Cũng lưu ý rằng việc chuyển đổi này chỉ xảy ra đối với các chức năng do người dùng xác định; . Cũng cần lưu ý rằng các hàm do người dùng định nghĩa là các 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;
chức năng máy phát điệnHàm hoặc phương thức sử dụng câu lệnh [xem phần ] được gọi là hàm tạo. Một hàm như vậy, khi được gọi, luôn trả về một đối tượng có thể được sử dụng để thực thi phần thân của hàm. gọi phương thức 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ách sử dụng câu lệnh
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule54. Khi hàm thực thi một câu lệnh hoặc rơi ra khỏi phần cuối, một ngoại lệ sẽ được đưa ra và trình vòng lặp sẽ đi đến phần cuối của tập hợp các giá trị được trả vềchức năng quy trình
Một hàm hoặc phương thức được định nghĩa bằng cách sử dụng được gọi là hàm coroutine. Một hàm như vậy, khi được gọi, sẽ trả về một đối tượng. Nó có thể chứa các biểu thức, cũng như và các câu lệnh. Xem thêm phần
Chức năng máy phát điện không đồng bộMột hàm hoặc phương thức được định nghĩa bằng cách sử dụng và sử dụng câu lệnh được gọi là hàm tạo không đồng bộ. Một hàm như vậy, khi được gọi, trả về một đối tượng có thể được sử dụng trong một câu lệnh để thực thi phần thân của hàm
Việc gọi phương thức của trình vòng lặp không đồng bộ sẽ trả về một phương thức 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. Khi hàm thực thi một câu lệnh trống hoặc rơi ra khỏi phần cuối, một ngoại lệ sẽ được đưa ra và trình lặp không đồng bộ sẽ đạt đến phần cuối của tập hợp các giá trị sẽ được tạo ra
Chức năng tích hợp sẵnMột đối tượng chức năng tích hợp là một trình bao bọc xung quanh một chức năng C. Ví dụ về các hàm tích hợp sẵn là và [ là mô-đun tích hợp sẵn 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.
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule09 là chuỗi tài liệu của hàm, hoặc
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8 nếu không có; Built-in methods
Đâ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ố phụ ngầm định. Một ví dụ về phương thức dựng sẵn là
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule80, 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
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule29 được đặt thành đối tượng được biểu thị bằng alistCác lớp học
Các lớp có thể gọi được. Các đối tượng này thường đóng vai trò là nhà máy cho các phiên bản mới của chính chúng, nhưng các biến thể có thể xảy ra đối với các loại lớp ghi đè. Các đối số của cuộc gọi được chuyển đến
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule82 và, trong trường hợp điển hình, để khởi tạo thể hiện mớiTrường hợp 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 một phương thức trong lớp của chúng
mô-đunCác mô-đun là một đơn vị tổ chức cơ bản của mã Python và được tạo bởi as được gọi bởi câu lệnh hoặc bằng cách gọi các hàm như và tích hợp sẵn. Một đối tượng mô-đun có một không gian tên được triển khai bởi một đối tượng từ điển [đây là từ điển được tham chiếu bởi thuộc tính
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule18 của các hàm được xác định trong mô-đun]. Tham chiếu thuộc tính được dịch sang tra cứu trong từ điển này, e. g. ,
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule90 is equivalent to
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule91. Đố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]
Gán thuộc tính cập nhật từ điển không gian tên của mô-đun, e. g. ,
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule92 tương đương với
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule93
Thuộc tính được xác định trước [có thể ghi]
Tên của mô-đun
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule09Chuỗi tài liệu của mô-đun hoặc
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8 nếu không cóTên đường dẫn của tệp mà mô-đun được tải từ đó, nếu nó được tải từ một tệp. Thuộc tính có thể bị thiếu đối với một số loại mô-đun, chẳng hạn như mô-đun C được liên kết tĩnh vào trình thông dịch. Đối với các mô-đun mở rộng được tải động từ thư viện dùng chung, đó là tên đường dẫn của tệp thư viện dùng chung
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule23Một từ điển chứa được thu thập trong quá trình thực thi thân mô-đun. Để biết các phương pháp hay nhất khi làm việc với
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule23, vui lòng xem
Thuộc tính chỉ đọc đặc biệt. là không gian tên của mô-đun như một đối tượng từ điển
Chi tiết triển khai CPython. Do cách CPython xóa từ điển mô-đun, 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ó tham chiếu trực tiếp. Để tránh điều này, hãy sao chép từ điển hoặc giữ nguyên mô-đun trong khi sử dụng trực tiếp từ điển của nó
lớp tùy chỉnhCác loại lớp tùy chỉnh thường được tạo bởi các định nghĩa lớp [xem phần ]. Một lớp có một không gian tên được triển khai bởi một đối tượng từ điển. Tham chiếu thuộc tính lớp được dịch sang tra cứu trong từ điển này, e. g. ,
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass02 được dịch thành
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass03 [mặc dù có một số dấu móc 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 tiếp tục trong các lớp cơ sở. 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 thừa kế 'kim cương' nơi có nhiều đường dẫn thừa kế dẫn trở lại tổ tiên chung. Chi tiết bổ sung về C3 MRO được sử dụng bởi Python có thể được tìm thấy trong tài liệu đi kèm với 2. 3 phát hành tại https. //www. con trăn. org/tải xuống/phát hành/2. 3/mro/
Khi một tham chiếu thuộc tính lớp [đối với lớp
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule43, chẳng hạn] sẽ tạo ra một đối tượng phương thức lớp, thì nó được chuyển đổi thành một đối tượng phương thức thể hiện có thuộc tính
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule29 là
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule43. Khi nó tạo ra một đối tượng phương thức tĩnh, nó đượ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 này để biết cách khác mà 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ự chứa trong lớp đó.
Các 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]
thuộc tính đặc biệt
thể hiện lớptên lớp
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule13Tên của mô-đun trong đó lớp được định nghĩa
Từ điển chứa không gian tên của lớp
Một bộ chứa các lớp cơ sở, theo thứ tự xuất hiện của chúng trong danh sách lớp cơ sở
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule09Chuỗi tài liệu của lớp, hoặc
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8 nếu không xác địnhimport sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule23Một từ điển chứa được thu thập trong quá trình thực thi nội dung lớp. Để biết các phương pháp hay nhất khi làm việc với
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule23, vui lòng xem
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 bên trên]. Một thể hiện của lớp có một không gian tên được triển khai dưới dạng từ điển, đây là nơi đầu tiên mà các tham chiếu thuộc tính được tìm kiếm. Khi một thuộc tính không được tìm thấy ở đó và lớp của đối tượng có một thuộc tính theo tên đó, quá trình 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 thể hiện có thuộc tính
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule29 là thể hiện. 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 phần này để biết cách khác mà 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 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ó một phương thức, 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 cá thể, không bao giờ là từ điển của lớp. Nếu lớp có phương thức hoặc, thì phương thức này được gọi thay vì cập nhật trực tiếp từ điển cá thể
Các thể hiện của lớp có thể giả vờ là số, trình tự 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. xem phần
thuộc tính đặc biệt. là từ điển thuộc tính;
Đối tượng I/O [còn được gọi là đối tượng tệp]A đại diện cho một tệp đang mở. Nhiều phím tắt có sẵn để tạo các đối tượng tệp. chức năng tích hợp sẵn, cũng như , và phương thức của các đối tượng ổ cắm [và có lẽ bởi các chức năng 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
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass27,
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass28 và
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass29 được khởi tạo để tạo các đối tượng tệp 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; các loại nội bộ
Một vài loại được trình thông dịch sử dụng nội bộ được hiển thị cho người dùng. Định nghĩa của chúng có thể thay đổi với 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 cho đầy đủ
đối tượng mãCác đối tượng mã đại diện cho mã Python thực thi được biên dịch theo byte hoặc. 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 trong đó nó được xác định], trong khi đối tượng mã không chứa ngữ cảnh; . Không giống như các đối tượng chức năng, 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
Thuộc tính chỉ đọc đặc biệt.
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass31 đưa ra tên hàm;
Các bit cờ sau đây được xác định cho
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass47. bit
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass49 is set if the function uses the
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass50 syntax to accept an arbitrary number of positional arguments; bit
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass51 is set if the function uses the
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass52 syntax to accept arbitrary keyword arguments; bit
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass53 is set if the function is a generator
Các khai báo tính năng trong tương lai [
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass54] cũng sử dụng các bit trong
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass47 để 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. bit
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass56 is set if the function was compiled with future division enabled; bits
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass57 and
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass58 were used in earlier versions of Python
Các bit khác trong
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass47 được dành riêng cho mục đích sử dụng nội bộ
Nếu một đối tượng mã đại diện cho một chức năng, mục đầu tiên trong
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass41 là chuỗi tài liệu của chức năng hoặc
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8 nếu không xác địnhđối tượng mã. co_positions[]
Trả về một lần lặp qua các vị trí mã nguồn của mỗi lệnh mã byte trong đối tượng mã
Trình vòng lặp trả về các bộ chứa
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass62. Bộ thứ i tương ứng với vị trí của mã nguồn được biên dịch theo lệnh thứ i. 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
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass
64Đang tải tệp pyc được biên dịch trong khi sử dụng
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass
64Vị trí các bộ dữ liệu tương ứng với các hướng dẫn nhân tạo
Số dòng và số cột không thể được biểu diễn do giới hạn triển khai cụ thể
Khi điều này xảy ra, một số hoặc tất cả các phần tử của bộ dữ liệu có thể được
Mới trong phiên bản 3. 11
Ghi chú
Tính năng này yêu cầu lưu trữ các vị trí cột trong các đối tượng mã, điều này có thể dẫn đến việc 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 in thông tin truy nguyên bổ sung, có thể sử dụng cờ dòng lệnh
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass64 hoặc biến môi trườngĐối tượng khung
Các đối tượng khung đại diện cho các khung thực thi. Chúng có thể xảy ra trong các đối tượng theo dõi [xem bên dưới] và cũng được chuyển đến các chức năng theo dõi đã đăng ký
Thuộc tính chỉ đọc đặc biệt.
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass71 là khung ngăn xếp trước đó [về phía người gọi] hoặc
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8 nếu đây là khung ngăn xếp dưới cùng;
Việc truy cập vào
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass73 sẽ tạo ra một
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass79 với các đối số
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass80 và
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass81
Special writable attributes.
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass82, nếu không phải là
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8, là một hàm được gọi cho các sự kiện khác nhau trong quá trình thực thi mã [cái này được trình gỡ lỗi sử dụng]. Thông thường, một sự kiện được kích hoạt cho mỗi dòng nguồn mới - điều này có thể bị vô hiệu hóa bằng cách đặt
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass84 thành
Việc triển khai có thể cho phép yêu cầu các sự kiện trên mỗi mã hành động bằng cách đặt
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass86 thành. Lưu ý rằng điều này có thể dẫn đến hành vi 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 đến hàm đang được theo dõi
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass88 is the current line number of the frame — writing to this from within a trace function jumps to the given line [only for the bottom-most frame]. 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 f_lineno
Các đối tượng khung hỗ trợ một phương thức
khung hình. clear[]Phương pháp này xóa tất cả các tham chiếu đến các biến cục bộ được giữ bởi khung. Ngoài ra, nếu khung thuộc về trình tạo, trình tạo được hoàn thành. Điều này giúp phá vỡ các chu kỳ tham chiếu liên quan đến các đối tượng khung [ví dụ: khi bắt một ngoại lệ và lưu trữ dấu vết của nó để sử dụng sau này]
được nâng lên nếu khung hiện đang thực thi
Mới trong phiên bản 3. 4
đối tượng truy nguyênCác đối tượng truy nguyên đại diện cho một dấu vết ngăn xếp của một ngoại lệ. Một đối tượng truy nguyên được tạo hoàn toàn khi xảy ra ngoại lệ và cũng có thể được tạo rõ ràng bằng cách gọi
Đối với các dấu vết được tạo hoàn toàn, 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, tại mỗi cấp độ không được kết nối, một đối tượng truy nguyên được chèn vào trước dấu vết hiện tại. Khi một trình xử lý ngoại lệ được nhập, dấu vết ngăn xếp sẽ được cung cấp cho chương trình. [Xem phần. ] Nó có thể truy cập dưới dạng mục thứ ba của bộ được trả về bởi
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass91 và dưới dạng thuộc tính
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass92 của ngoại lệ đã 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 được ghi [được định dạng độc đáo] vào luồng lỗi tiêu chuẩn;
Đối với các dấu vết được tạo rõ ràng, người tạo dấu vết phải xác định cách liên kết các thuộc tính
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass94 để tạo thành một dấu vết ngăn xếp đầy đủ
Thuộc tính chỉ đọc đặc biệt.
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass95 điểm vào khung thi hành của mức hiện tại; . Số dòng và lệnh cuối cùng trong truy nguyên có thể khác với số dòng của đối tượng khung của nó nếu ngoại lệ xảy ra trong một câu lệnh không có mệnh đề ngoại trừ phù hợp hoặc với mệnh đề cuối cùng
Truy cập vào
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass95 sẽ tạo ra một
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass79 với các đối số
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass80 và
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']02
Thuộc tính có thể ghi đặc biệt.
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass94 là cấp độ tiếp theo trong theo dõi ngăn xếp [đối với khung nơi xảy ra ngoại lệ] hoặc
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8 nếu không có cấp độ tiếp theo
Đã thay đổi trong phiên bản 3. 7. Các đối tượng truy nguyên giờ đây có thể được khởi tạo rõ ràng từ mã Python và thuộc tính
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass94 của các phiên bản hiện có có thể được cập nhật. Cắt đối tượng
Các đối tượng lát cắt được sử dụng để biểu diễn các lát cắt cho các phương thức. Chúng cũng được tạo bởi chức năng tích hợp
Special read-only attributes.
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']08 là giới hạn dưới; . Các thuộc tính này có thể có bất kỳ kiểu nào
Các đối tượng lát hỗ trợ một phương thức
lát. chỉ số[bản thân , độ dài]Phương thức này lấy một đối số số nguyên có độ dài duy nhất 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 có độ dài. Nó trả về một bộ ba số nguyên; . Các chỉ số bị thiếu hoặc nằm ngoài giới hạn được xử lý theo cách nhất quán với các lát cắt thông thường
Đối tượng phương thức tĩnhCác đối tượng phương thức tĩnh cung cấp một cách đánh bại việc chuyển đổi các đối tượng chức năng 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 định nghĩa. Khi một đối tượng phương thức tĩnh được truy xuất 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ỳ 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 tích hợp
Đối tượng phương thức lớpMộ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, trong phần "Phương thức do người dùng định nghĩa". Các đối tượng phương thức lớp được tạo bởi hàm tạo 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 được gọi theo cú pháp đặc biệt [chẳng hạn như các phép toán số học hoặc đăng ký và cắt lớp] bằng cách định nghĩa các phương thức có tên đặc biệt. Đây là cách tiếp cận của Python để nạp chồng toán tử, cho phép các lớp xác định hành vi của chính chúng đối với các toán tử ngôn ngữ. Chẳng hạn, nếu một lớp định nghĩa một phương thức có tên và
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass0 là một thể hiện của lớp này, thì
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']16 gần tương đương với
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']17. Trừ khi được đề cập, các nỗ lực thực hiện một thao tác sẽ tạo ra một ngoại lệ khi không có phương thức thích hợp nào được xác định [thường là hoặc ]
Đặt một phương thức đặc biệt thành
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8 cho biết rằng thao tác tương ứng không khả dụng. Ví dụ: nếu một lớp được đặt thành
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8, thì lớp đó không thể lặp lại, do đó, việc gọi các thể hiện của nó sẽ tăng [không quay lại ].
Khi triển khai một lớp mô phỏng bất kỳ loại dựng sẵn 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ố trình tự 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
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']26 trong Mô hình Đối tượng Tài liệu của W3C. ]
3. 3. 1. Tùy chỉnh cơ bản
đối tượng. __new__[cls[ , . ...]]Được gọi để tạo một thể hiện mới của lớp cls. là một phương thức tĩnh [có trường hợp đặc biệt nên bạn không cần khai báo nó như vậy] lấy lớp mà một thể hiện được yêu cầu làm đối số đầu tiên của 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 đến lớp]. Giá trị trả về của phải là thể hiện đối tượng mới [thường là thể hiện của cls]
Các triển khai điển hình tạo một thể hiện mới của lớp bằng cách gọi phương thức của lớp cha bằng cách sử dụng
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']30 với các đối số thích hợp và sau đó sửa đổi thể hiện mới được tạo nếu cần trước khi trả lại nó
Nếu được gọi trong quá trình xây dựng đối tượng và nó trả về một thể hiện của cls, thì phương thức của thể hiện mới sẽ được gọi như
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']33, trong đó self là thể hiệ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 không trả về một thể hiện của cls, thì phương thức của thể hiện mới sẽ không được gọi
chủ yếu nhằm mục đích cho phép các lớp con thuộc loại bất biến [như int, str hoặc tuple] tùy chỉnh việc tạo cá thể. 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
đối tượng. __init__[bản thân[ , . ...]]Được gọi sau khi phiên bản đã được tạo [bởi ], nhưng trước khi nó được trả lại 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, thì phương thức 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 thể hiện; .
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']40
Bởi vì và làm việc cùng nhau trong việc xây dựng các đối tượng [ để tạo ra nó và để tùy chỉnh nó], không có giá trị nào không phải ______4_______8 có thể được trả về bởi ;
đối tượng. __del__[bản thân]Được gọi khi instance sắp bị hủy. Đây còn được gọi là bộ hoàn thiện hoặc [không chính xác] là bộ hủy. Nếu một lớp cơ sở có một phương thức, thì phương thức 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 thể hiện
Có thể [mặc dù không nên. ] cho phương thức trì hoãn việc hủy đối tượng bằng cách tạo một tham chiếu mới cho nó. Đây được gọi là hồi sinh đối tượng. Nó phụ thuộc vào việc triển khai 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ị hủy;
Không đảm bảo rằng các phương thức được gọi cho các đối tượng vẫn tồn tại khi trình thông dịch thoát
Ghi chú
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']53 không gọi trực tiếp
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']54 - cái trước giảm số lượng tham chiếu cho
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass0 đi một và cái sau chỉ được gọi khi số lượng tham chiếu của
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass0 bằng 0
Chi tiết triển khai CPython. Có thể cho một chu kỳ tham chiếu để ngăn số lượng tham chiếu của một đối tượng về 0. Trong trường hợp này, chu kỳ sẽ được phát hiện và xóa sau đó bởi. Một nguyên nhân phổ biến của các chu kỳ tham chiếu là khi một ngoại lệ bị bắt trong một biến cục bộ. Sau đó, các cục bộ của khung tham chiếu ngoại lệ, ngoại lệ này tham chiếu truy nguyên của chính nó, ngoại lệ này tham chiếu các cục bộ của tất cả các khung được bắt trong truy nguyên
Xem thêm
Tài liệu cho mô-đun
Cảnh báo
Do các trường hợp bấp bênh mà theo đó các phương thức đượ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 tới
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass29. Đặc biệt
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 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ế tắc vì tài nguyên có thể đã bị chiếm bởi mã bị gián đoạn để thực thi
có thể được thực thi trong khi tắt trình thông dịch. Do đó, các biến toàn cục mà nó cần truy cập [bao gồm cả các mô-đun khác] có thể đã bị xóa hoặc được đặt thành
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']
8. Python đảm bảo rằng các hình cầu 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 hình cầu khác bị xóa;
Được gọi bởi hàm tích hợp để 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ể, đây sẽ 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ị [với 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
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']67 phải được trả lại. Giá trị trả về phải là một đối tượng chuỗi. Nếu một lớp định nghĩa nhưng không định nghĩa, thì cũng được sử dụng khi cần một biểu diễn chuỗi “không chính thức” của các thể hiệ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à biểu diễn phải giàu thông tin và rõ ràng
đối tượng. __str__[bản thân]Được gọi bởi và các hàm tích hợp và để tính toán biểu diễn chuỗi "không chính thức" hoặc có thể in được của một đối tượng. Giá trị trả về phải là một đối tượng
Phương thức này khác ở chỗ không có kỳ vọng trả về một biểu thức Python hợp lệ. một đại diện thuận tiện hơn hoặc ngắn gọn có thể được sử dụng
Việc triển khai mặc định được xác định bởi các cuộc gọi loại tích hợp
đối tượng. __bytes__[bản thân]Được gọi bởi để tính toán biểu diễn chuỗi byte của một đối tượng. Điều này sẽ trả lại một đối tượng
đối tượng. __format__[bản thân , format_spec]Được gọi bởi hàm tích hợp và bằng cách mở rộng, đánh giá và phương thức, để tạo ra một 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 thực hiện, 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 tích hợp sẵn hoặc sử dụng cú pháp tùy chọn định dạng tương tự
Xem 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
Đã thay đổi trong phiên bản 3. 4. Phương thức __format__ của
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']76 tự nó tạo ra một chuỗi ký tự không rỗng nếu được truyền vào.
Đã thay đổi trong phiên bản 3. 7. ______4_______84 bây giờ tương đương với
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']85 thay vì
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']86. đối tượng. __lt__[bản thân , khác . ]object.__le__[bản thân , khác . ]object.__eq__[bản thân , khác . ]object.__ne__[bản thân , khác . ]object.__gt__[bản thân , khác . ]object.__ge__[bản thân , khác]
Đây là những phương pháp được gọi là “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.
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']87 cuộc gọi
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']88,
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']89 cuộc gọi
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']90,
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']91 cuộc gọi
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']92,
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']93 cuộc gọi
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']94,
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']95 cuộc gọi
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']96 và
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']97 cuộc gọi
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']98
Một phương thức so sánh phong phú có thể trả về singleton
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']9 nếu nó không thực hiện thao tác cho một cặp đối số đã cho. Theo quy ước,
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass1 và
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass2 được trả lại để 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 [e. g. , trong điều kiện của câu lệnh
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook02], Python sẽ gọi giá trị để xác định xem kết quả là đúng hay sai
Theo mặc định,
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']76 thực hiện bằng cách sử dụng
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule7, trả về
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']9 trong trường hợp so sánh sai.
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook08. Đối với , theo mặc định, nó ủy quyền và đảo ngược kết quả trừ khi nó là
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']9. Không có mối quan hệ ngụ ý nào khác giữa các toán tử so sánh hoặc triển khai mặc định; . Để tự động tạo các hoạt động đặt hàng từ một hoạt động gốc, hãy xem
Xem đoạn trên để biết một số lưu ý quan trọng về cách tạo các đối tượng hỗ trợ các thao tác 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ì hỗ trợ]; . Nếu các toán hạng thuộc các 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 được phản ánh của toán hạng bên phải sẽ đượ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
đối tượng. __hash__[bản thân]Được gọi bởi chức năng tích hợp và cho các hoạt động trên các thành viên của bộ sưu tập được băm bao gồm , và. Phương thức
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook15 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; . Ví dụ
def __hash__[self]: return hash[[self.name, self.nick, self.color]]
Ghi chú
cắt bớt giá trị được trả về từ phương thức tùy chỉnh của đối tượng thành kích thước của mộ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 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 chiều 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à với
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook31
Nếu một lớp không định nghĩa một phương thức thì nó cũng không định nghĩa một thao tác; . Nếu một lớp định nghĩa các đối tượng có thể thay đổi và triển khai một phương thức, thì lớp đó không nên triển khai, vì việc triển khai các bộ sưu tập có thể băm yêu cầu giá trị băm của khóa là bất biến [nếu giá trị băm của đối tượng thay đổi, nó sẽ nằm trong nhóm băm sai]
Các lớp do người dùng định nghĩa có và các phương thức theo mặc định;
Một lớp ghi đè và không xác định sẽ được đặt ngầm định thành
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8. Khi phương thức của một lớp là
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8, các thể hiện của lớp sẽ đưa ra một giá trị 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
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook51
Nếu một lớp ghi đè cần giữ lại việc triển khai từ lớp cha, thì trình thông dịch phải được thông báo điều này một cách rõ ràng bằng cách đặt
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook54
Nếu một lớp không ghi đè muốn chặn hỗ trợ băm, thì lớp đó phải bao gồm
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook56 trong định nghĩa lớp. Một lớp định nghĩa riêng của nó làm tăng a một cách rõ ràng sẽ được xác định không chính xác là có thể băm bởi một lệnh gọi
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook51
Ghi chú
Theo mặc định, các giá trị của các đối tượng str và bytes được "muối" với 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 cung cấp khả năng bảo vệ chống lại tấn công từ chối dịch vụ gây ra bởi 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 http. //www. chứng chỉ. org/advisory/ocert-2011-003. html để biết chi tiết
Thay đổi giá trị băm ảnh hưởng đến thứ tự lặp lại của các tập hợp. Python chưa bao giờ đảm bảo về thứ tự này [và nó thường khác nhau giữa các bản dựng 32 bit và 64 bit]
Xem thêm
Đã thay đổi trong phiên bản 3. 3. Băm ngẫu nhiên được bật theo mặc định.
đối tượng. __bool__[bản thân]Được gọi để thực hiện kiểm tra giá trị thực và hoạt động tích hợp sẵn
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook03; . Khi phương thức này không được xác định, đượ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 không. Nếu một lớp định nghĩa không phải là không, thì tất cả các thể hiện của nó đượ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
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook68] cho các thể hiện của lớpđối tượng. __getattr__[bản thân , tên]
Được gọi khi truy cập thuộc tính mặc định không thành công với một [hoặc tăng bởi vì tên không phải là thuộc tính thực thể hoặc thuộc tính trong cây lớp cho
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook72; hoặc của thuộc tính tên tăng ]. Phương thức này sẽ trả về giá trị thuộc tính [đã tính] hoặc đưa ra một ngoại lệ
Lưu ý rằng nếu thuộc tính được tìm thấy thông qua cơ chế thông thường, thì không được gọi. [Đây là sự bất đối xứng có chủ ý giữa và. ] Điều này được thực hiện vì cả lý do hiệu quả và vì nếu không thì sẽ không có cách nào để truy cập các thuộc tính khác của thể hiện. Lưu ý rằng ít nhất đối với các biến mẫu, bạn có thể giả mạo toàn quyền kiểm soát 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 bên dưới để biết cách thực sự có toàn quyền kiểm soát đối với quyền truy cập thuộc tính
đối tượng. __getattribute__[bản thân , tên]Đượ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, thì lớp sau sẽ không được gọi trừ khi gọi nó một cách rõ ràng hoặc đưa ra một. Phương thức này sẽ trả về giá trị thuộc tính [đã tính] hoặc đưa ra một ngoại lệ. Để tránh đệ quy vô hạn trong phương thức này, việc triển khai của 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 mà nó cần, ví dụ:
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook85
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ời gọi ngầm thông qua cú pháp ngôn ngữ hoặc các hàm tích hợp. Nhìn thấy
Đối với các truy cập thuộc tính nhạy cảm nhất định, hãy tăng một
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass79 với các đối số
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass80 và
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook88đối tượng. __setattr__[bản thân , tên, value]
Được gọi khi thử gán thuộc tính. Điều này được gọi thay vì cơ chế bình thường [i. e. lưu trữ giá trị trong từ điển cá thể]. name là tên thuộc tính, value là giá trị được gán cho nó
Nếu muốn gán cho một thuộc tính thể hiện, nó nên gọi phương thức của lớp cơ sở có cùng tên, ví dụ,
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook90
Đối với một số phép gán thuộc tính nhạy cảm, hãy tăng một
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook91 với các đối số
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass80,
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook88,
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook94
Thích 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
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook96 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, hãy tăng
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook97 với các đối số
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass80 và
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook88đối tượng. __dir__[bản thân]
Được gọi khi được gọi trên đối tượng. Một chuỗi phải được trả lại. chuyển đổi chuỗi 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
Tên đặc biệt
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass02 và
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass03 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
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass02 ở 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 giá trị. Nếu một thuộc tính không được tìm thấy trên một đối tượng mô-đun thông qua tra cứu thông thường, tôi. e. , thì
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass02 được tìm kiếm trong mô-đun
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule19 trước khi tăng. Nếu tìm thấy, nó được gọi với tên thuộc tính và kết quả được trả về
Hàm
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass03 không được chấp nhận đối số và trả về một chuỗi các chuỗi đại diện cho các tên có thể truy cập trên mô-đun. Nếu có, chức năng này sẽ ghi đè tìm kiếm tiêu chuẩn trên một mô-đun
Để tùy chỉnh chi tiết hơn về hành vi của mô-đun [đặt thuộc tính, thuộc tính, v.v. ], người ta có thể đặt thuộc tính
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass22 của một đối tượng mô-đun thành một lớp con của. Ví dụ
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule
Ghi chú
Việc xác định mô-đun
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass02 và đặt mô-đun
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass22 chỉ ảnh hưởng đến các tra cứu được thực hiện bằng cú pháp truy cập thuộc tính – truy cập trực tiếp vào toàn cầu của mô-đun [dù bằng mã trong mô-đun hay thông qua tham chiếu đến từ điển toàn cầu của mô-đun] đều không bị ảnh hưởng
Đã thay đổi trong phiên bản 3. 5. ______1_______22 thuộc tính mô-đun hiện có thể ghi.
Mới trong phiên bản 3. 7. ______17_______02 và
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass03 thuộc tính mô-đun.
Xem thêm
PEP 562 - Mô-đun __getattr__ và __dir__Mô tả các chức năng
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass02 và
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass03 trên các mô-đun
3. 3. 2. 2. Mô tả triển khai
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ái gọi là lớp mô tả] xuất hiện trong lớp chủ sở hữu [bộ mô tả phải nằm 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 lớp cha 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 lớp chủ sở hữu '
đối tượng. __get__[bản thân , thể hiện, owner=None]Được gọi để lấy thuộc tính của lớp chủ sở hữu [truy cập thuộc tính lớp] hoặc của một thể hiện của lớp đó [truy cập thuộc tính thể hiện]. Đối số chủ sở hữu tùy chọn là lớp chủ sở hữu, trong khi thể hiện là phiên bản mà thuộc tính được truy cập thông qua hoặc
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8 khi thuộc tính được truy cập thông qua chủ sở hữu
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ệ
PEP 252 chỉ định 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; . Việc triển khai riêng của Python luôn chuyển vào cả hai đối số cho dù chúng có bắt buộc hay không
đối tượng. __set__[bản thân , thể hiện, value]Được gọi để đặt thuộc tính trên một thể hiện của lớp chủ sở hữu thành một giá trị mới, giá trị
Lưu ý, thêm hoặc thay đổi loại bộ mô tả thành “bộ mô tả dữ liệu”. Xem để biết thêm chi tiết
đối tượng. __delete__[bản thân , thể hiện]Được gọi để xóa thuộc tính trên một thể hiện của lớp chủ sở hữu
Thuộc tính
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass28 được mô-đun hiểu là chỉ định lớp nơi đối tượng này được xác định [việc đặt thuộc tính này một cách thích hợp có thể hỗ trợ trong thời gian chạy nội quan của các thuộc tính lớp động]. Đối với các hàm có thể gọi được, nó có thể chỉ ra rằng một thể hiệ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 bộ mô tả
Nói chung, một bộ mô tả là một thuộc tính đối tượng có "hành vi ràng buộc", một thuộc tính có quyền truy cập thuộc tính đã bị các phương thức trong giao thức mô tả ghi đè. , , Và. 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. Chẳng hạn,
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass33 có chuỗi tra cứu bắt đầu bằng
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass34, sau đó là
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass35 và tiếp tục thông qua các lớp cơ sở của
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass36 không bao gồm 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ế. Điều này xảy ra ở đâu trong chuỗi ưu tiên phụ thuộc vào phương pháp mô tả nào được xác định và cách chúng được gọi
Điểm khởi đầu cho lời gọi bộ mô tả là một ràng buộc,
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass33. Cách lập luận phụ thuộc vào
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']0Gọi trực tiếp
Cuộc gọi đơn giản nhất 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ả.
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass39Ràng buộc sơ thẩm
Nếu liên kết với một thể hiện đối tượng, thì
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass33 được chuyển thành cuộc gọi.
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass41Ràng buộc lớp
Nếu ràng buộc với một lớp,
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass42 được chuyển thành cuộc gọi.
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass43siêu ràng buộc
Một tra cứu chấm, chẳng hạn như
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass44 tìm kiếm
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass45 cho một lớp cơ sở
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass46 theo sau
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass47 và sau đó trả về
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass48. Nếu không phải là một bộ mô tả,
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass0 được trả về không thay đổi
Đối với các liên kết thể hiện, mức độ ưu tiên của lời 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 , và. Nếu nó không xác định
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook73, thì việc truy cập 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 thể hiện của đối tượng. Nếu bộ mô tả xác định
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass26 và/hoặc
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass27, thì đó là bộ mô tả dữ liệu; . Thông thường, bộ mô tả dữ liệu xác định cả
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook73 và
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass26, trong khi bộ mô tả phi dữ liệu chỉ có phương thức
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook73. Bộ mô tả dữ liệu có định nghĩa
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook73 và
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass26 [và/hoặc
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass27] luôn ghi đè định nghĩa lại trong từ điển mẫu. Ngược lại, các bộ mô tả phi dữ liệu có thể bị ghi đè bởi các trường hợp
Các phương thức Python [bao gồm cả các phương thức được trang trí bằng và ] được triển khai dưới dạng mô tả phi dữ liệu. Theo đó, các thể hiện có thể xác định lại và ghi đè các phương thức. Điều này cho phép các phiên bản riêng lẻ có được các hành vi khác với các phiên bản khác của cùng một lớp
Chức năng được thực hiện như một bộ mô tả dữ liệu. Theo đó, các trường hợp không thể ghi đè hành vi của một thuộc tính
3. 3. 2. 4. __slots__
__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 và __weakref__ [trừ khi được khai báo rõ ràng trong __slots__ hoặc có sẵn trong cha mẹ. ]
Không gian tiết kiệm được khi sử dụng có thể là đáng kể. Tốc độ tra cứu thuộc tính cũng có thể được cải thiện đáng kể
đối tượng. __slots__Biến lớp này có thể được gán một chuỗi, có thể lặp lại hoặc chuỗi các chuỗi có tên biến được sử dụng bởi các thể hiện. __slots__ dự trữ không gian cho các biến đã khai báo và ngăn chặn việc tạo tự động và __weakref__ cho từng trường hợp
Khi kế thừa từ một lớp không có __slots__, thuộc tính and __weakref__ của các phiên bản sẽ luôn có thể truy cập được
Không có biến, 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ê tăng. Nếu muốn gán động các biến mới, thì hãy thêm
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass
71 vào chuỗi các chuỗi trong khai báo __slots__Không có biến __weakref__ cho mỗi phiên bản, các lớp xác định __slots__ không hỗ trợ cho các phiên bản của nó. Nếu cần hỗ trợ tham chiếu yếu, hãy thêm
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass
73 vào chuỗi chuỗi trong khai báo __slots____slots__ được triển khai ở cấp lớp bằng cách tạo cho từng tên biến. Do đó, không thể sử dụng các thuộc tính lớp để đặt giá trị mặc định cho các biến thể hiện được xác định bởi __slots__;
Hành động của khai báo __slots__ không giới hạn ở lớp nơi nó được định nghĩa. __slots__ được khai báo trong cha mẹ có sẵn trong các lớp con. Tuy nhiên, các lớp con sẽ nhận được a và __weakref__ trừ khi chúng cũng xác định __slots__ [chỉ nên chứa tên của bất kỳ vị trí bổ sung nào]
If a class defines a slot also defined in a base class, the instance variable defined by the base class slot is inaccessible [except by retrieving its descriptor directly from the base class]. Điều này làm cho ý nghĩa của chương trình không 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
Nonempty __slots__ does not work for classes derived from “variable-length” built-in types such as , and
Any non-string may be assigned to __slots__
If a is used to assign __slots__, the dictionary keys will be used as the slot names. The values of the dictionary can be used to provide per-attribute docstrings that will be recognised by and displayed in the output of
assignment works only if both classes have the same __slots__
with multiple slotted parent classes can be used, but only one parent is allowed to have attributes created by slots [the other bases must have empty slot layouts] - violations raise
If an is used for __slots__ then a is created for each of the iterator’s values. However, the __slots__ attribute will be an empty iterator
3. 3. 3. Customizing class creation
Whenever a class inherits from another class, is called on the parent class. This way, it is possible to write classes which change the behavior of subclasses. This is closely related to class decorators, but where class decorators only affect the specific class they’re applied to,
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass84 solely applies to future subclasses of the class defining the methodclassmethod 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 is then the new subclass. If defined as a normal instance method, this method is implicitly converted to a class method
Keyword arguments which are given to a new class are passed to the parent’s class
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass84. For compatibility with other classes using
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass84, one should take out the needed keyword arguments and pass the others over to the base class, as in
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass
The default implementation
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass87 does nothing, but raises an error if it is called with any arguments
Ghi chú
The metaclass hint
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass88 is consumed by the rest of the type machinery, and is never passed to
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass84 implementations. The actual metaclass [rather than the explicit hint] can be accessed as
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass90
New in version 3. 6
When a class is created,
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass91 scans the class variables and makes callbacks to those with a hookobject. __set_name__[self , owner , name]
Automatically called at the time the owning class owner is created. The object has been assigned to name in that class
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']
If the class variable is assigned after the class is created, will not be called automatically. If needed, can be called directly
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook
See for more details
New in version 3. 6
3. 3. 3. 1. Metaclasses
By default, classes are constructed using . The class body is executed in a new namespace and the class name is bound locally to the result of
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass96
The class creation process can be customized by passing the
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass88 keyword argument in the class definition line, or by inheriting from an existing class that included such an argument. In the following example, both
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass98 and
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass99 are instances of
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]00
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass
Any other keyword arguments that are specified in the class definition are passed through to all metaclass operations described below
When a class definition is executed, the following steps occur
MRO entries are resolved;
the appropriate metaclass is determined;
the class namespace is prepared;
the class body is executed;
the class object is created
3. 3. 3. 2. Resolving MRO entries
If a base that appears in class definition is not an instance of , then an
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]02 method is searched on it. If found, it is called with the original bases tuple. This method must return a tuple of classes that will be used instead of this base. The tuple may be empty, in such case the original base is ignored
Xem thêm
PEP 560 - Core support for typing module and generic types
3. 3. 3. 3. Determining the appropriate metaclass
The appropriate metaclass for a class definition is determined as follows
if no bases and no explicit metaclass are given, then is used;
if an explicit metaclass is given and it is not an instance of , then it is used directly as the metaclass;
if an instance of is given as the explicit metaclass, or bases are defined, then the most derived metaclass is used
The most derived metaclass is selected from the explicitly specified metaclass [if any] and the metaclasses [i. e.
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass90] of all specified base classes. The most derived metaclass is one which is a subtype of all of these candidate metaclasses. If none of the candidate metaclasses meets that criterion, then the class definition will fail with
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook2
3. 3. 3. 4. Preparing the class namespace
Once the appropriate metaclass has been identified, then the class namespace is prepared. If the metaclass has a
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]08 attribute, it is called as
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]09 [where the additional keyword arguments, if any, come from the class definition]. The
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]08 method should be implemented as a . The namespace returned by
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]08 is passed in to
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]13, but when the final class object is created the namespace is copied into a new
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook25
If the metaclass has no
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]08 attribute, then the class namespace is initialised as an empty ordered mapping
Xem thêm
PEP 3115 - Metaclasses in Python 3000Introduced the
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]08 namespace hook
3. 3. 3. 5. Executing the class body
The class body is executed [approximately] as
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]17. The key difference from a normal call to is that lexical scoping allows the class body [including any methods] to reference names from the current and outer scopes when the class definition occurs inside a function
However, even when the class definition occurs inside the function, methods defined inside the class still cannot see names defined at the class scope. Class variables must be accessed through the first parameter of instance or class methods, or through the implicit lexically scoped
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass22 reference described in the next section
3. 3. 3. 6. Creating the class object
Once the class namespace has been populated by executing the class body, the class object is created by calling
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]20 [the additional keywords passed here are the same as those passed to
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]08]
This class object is the one that will be referenced by the zero-argument form of .
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass22 is an implicit closure reference created by the compiler if any methods in a class body refer to either
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass22 or
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]25. This allows the zero argument form of to correctly identify the class being defined based on lexical scoping, while the class or instance that was used to make the current call is identified based on the first argument passed to the method
CPython implementation detail. In CPython 3. 6 and later, the
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass22 cell is passed to the metaclass as a
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]28 entry in the class namespace. If present, this must be propagated up to the
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]29 call in order for the class to be initialised correctly. Failing to do so will result in a in Python 3. 8
When using the default metaclass , or any metaclass that ultimately calls
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]29, the following additional customization steps are invoked after creating the class object
Phương thức
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]
29 thu thập tất cả các thuộc tính trong không gian tên lớp xác định một phương thức;Those
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]
35 methods are called with the class being defined and the assigned name of that particular attribute;The hook is called on the immediate parent of the new class in its method resolution order
After the class object is created, it is passed to the class decorators included in the class definition [if any] and the resulting object is bound in the local namespace as the defined class
When a new class is created by
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]29, the object provided as the namespace parameter is copied to a new ordered mapping and the original object is discarded. The new copy is wrapped in a read-only proxy, which becomes the attribute of the class object
Xem thêm
PEP 3135 - New superDescribes the implicit
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass22 closure reference
3. 3. 3. 7. Uses for metaclasses
The potential uses for metaclasses are boundless. Some ideas that have been explored include enum, logging, interface checking, automatic delegation, automatic property creation, proxies, frameworks, and automatic resource locking/synchronization
3. 3. 4. Customizing instance and subclass checks
The following methods are used to override the default behavior of the and built-in functions
In particular, the metaclass implements these methods in order to allow the addition of Abstract Base Classes [ABCs] as “virtual base classes” to any class or type [including built-in types], including other ABCs
class. __instancecheck__[self , instance]Return true if instance should be considered a [direct or indirect] instance of class. If defined, called to implement
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]43class. __subclasscheck__[self , subclass]
Return true if subclass should be considered a [direct or indirect] subclass of class. If defined, called to implement
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]44
Note that these methods are looked up on the type [metaclass] of a class. They cannot be defined as class methods in the actual class. This is consistent with the lookup of special methods that are called on instances, only in this case the instance is itself a class
Xem thêm
PEP 3119 - Introducing Abstract Base ClassesIncludes the specification for customizing and behavior through and , with motivation for this functionality in the context of adding Abstract Base Classes [see the module] to the language
3. 3. 5. Emulating generic types
When using , it is often useful to parameterize a using Python’s square-brackets notation. For example, the annotation
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]50 might be used to signify a in which all the elements are of type
Xem thêm
PEP 484 - Type HintsIntroducing Python’s framework for type annotations
Documentation for objects representing parameterized generic classes
, andDocumentation on how to implement generic classes that can be parameterized at runtime and understood by static type-checkers
A class can generally only be parameterized if it defines the special class method
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]54classmethod object. __class_getitem__[cls , key]
Return an object representing the specialization of a generic class by type arguments found in key
When defined on a class,
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]54 is automatically a class method. As such, there is no need for it to be decorated with when it is defined
3. 3. 5. 1. The purpose of __class_getitem__
The purpose of is to allow runtime parameterization of standard-library generic classes in order to more easily apply to these classes
To implement custom generic classes that can be parameterized at runtime and understood by static type-checkers, users should either inherit from a standard library class that already implements , or inherit from , which has its own implementation of
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]54
Custom implementations of on classes defined outside of the standard library may not be understood by third-party type-checkers such as mypy. Using
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]54 on any class for purposes other than type hinting is discouraged
3. 3. 5. 2. __class_getitem__ versus __getitem__
Usually, the of an object using square brackets will call the instance method defined on the object’s class. However, if the object being subscribed is itself a class, the class method may be called instead.
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]54 should return a object if it is properly defined
Presented with the
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]66, the Python interpreter follows something like the following process to decide whether or should be called
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]
In Python, all classes are themselves instances of other classes. Lớp của một lớp được gọi là lớp đó và hầu hết các lớp đều có lớp đó là siêu dữ liệu của chúng. không xác định , nghĩa là các biểu thức như
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]50,
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]73 và
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]74 đều dẫn đến việc được gọi
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]
Tuy nhiên, nếu một lớp có siêu dữ liệu tùy chỉnh xác định, thì việc đăng ký lớp đó có thể dẫn đến hành vi khác. Một ví dụ về điều này có thể được tìm thấy trong mô-đun
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]
Xem thêm
PEP 560 - Hỗ trợ cốt lõi để nhập mô-đun và các loại chungGiới thiệu và phác thảo khi một kết quả trong
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]54 được gọi thay vì
3. 3. 6. Emulating callable objects
object. __call__[self[ , args. ]]Called when the instance is “called” as a function; if this method is defined,
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]81 roughly translates to
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]82
3. 3. 7. Emulating container types
The following methods can be defined to implement container objects. Containers usually are [such as or ] or [like ], but can represent other containers as well. The first set of methods is used either to emulate a sequence or to emulate a mapping; the difference is that for a sequence, the allowable keys should be the integers k for which
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]86 where N is the length of the sequence, or objects, which define a range of items. It is also recommended that mappings provide the methods
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]88,
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]89,
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]90,
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]91,
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]92,
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]93,
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]94,
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]95,
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]96, and
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]97 behaving similar to those for Python’s standard objects. The module provides a to help create those methods from a base set of , , , and
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]88. Mutable sequences should provide methods
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]05,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]06,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]07,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]08,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]09,
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]94,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]11,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]12 and
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]13, like Python standard objects. Cuối cùng, các loại trình tự nên thực hiện 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 , , , và được mô tả bên dưới; . It is recommended that both mappings and sequences implement the method to allow efficient use of the
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]22 operator; for mappings,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]22 should search the mapping’s keys; for sequences, it should search through the values. It is further recommended that both mappings and sequences implement the method to allow efficient iteration through the container; for mappings,
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']21 should iterate through the object’s keys; for sequences, it should iterate through the valuesobject. __len__[self]
Called to implement the built-in function . Should return the length of the object, an integer
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]9 0. Also, an object that doesn’t define a method and whose method returns zero is considered to be false in a Boolean context
CPython implementation detail. In CPython, the length is required to be at most . If the length is larger than
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]30 some features [such as ] may raise . To prevent raising
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]33 by truth value testing, an object must define a methodobject. __length_hint__[self]
Called to implement . Should return an estimated length for the object [which may be greater or less than the actual length]. The length must be an integer
from inspect import isclass def subscribe[obj, x]: """Return the result of the expression 'obj[x]'""" class_of_obj = type[obj] # If the class of obj defines __getitem__, # call class_of_obj.__getitem__[obj, x] if hasattr[class_of_obj, '__getitem__']: return class_of_obj.__getitem__[obj, x] # Else, if obj is a class and defines __class_getitem__, # call obj.__class_getitem__[x] elif isclass[obj] and hasattr[obj, '__class_getitem__']: return obj.__class_getitem__[x] # Else, raise an exception else: raise TypeError[ f"'{class_of_obj.__name__}' object is not subscriptable" ]9 0. The return value may also be , which is treated the same as if the
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]39 method didn’t exist at all. This method is purely an optimization and is never required for correctness
Mới trong phiên bản 3. 4
Ghi chú
Slicing is done exclusively with the following three methods. A call like
a[1:2] = b
is translated to
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule0
and so forth. Missing slice items are always filled in with
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8object. __getitem__[self , key]
Called to implement evaluation of
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]41. For types, the accepted keys should be integers and slice objects. Note that the special interpretation of negative indexes [if the class wishes to emulate a type] is up to the method. If key is of an inappropriate type, may be raised; if of a value outside the set of indexes for the sequence [after any special interpretation of negative values], should be raised. For types, if key is missing [not in the container], should be raised
Ghi chú
loops expect that an will be raised for illegal indexes to allow proper detection of the end of the sequence
Ghi chú
When a class, the special class method may be called instead of
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']06. See for more detailsobject. __setitem__[self , key , value]
Called to implement assignment to
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]41. Same note as for . This should only be implemented for mappings if the objects support changes to the values for keys, or if new keys can be added, or for sequences if elements can be replaced. The same exceptions should be raised for improper key values as for the methodobject. __delitem__[self , key]
Called to implement deletion of
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]41. Same note as for . This should only be implemented for mappings if the objects support removal of keys, or for sequences if elements can be removed from the sequence. The same exceptions should be raised for improper key values as for the methodobject. __missing__[self , key]
Called by . to implement
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]41 for dict subclasses when key is not in the dictionaryobject. __iter__[self]
This method is called when an is required for a container. This method should return a new iterator object that can iterate over all the objects in the container. For mappings, it should iterate over the keys of the container
object. __reversed__[self]Called [if present] by the built-in to implement reverse iteration. It should return a new iterator object that iterates over all the objects in the container in reverse order
If the method is not provided, the built-in will fall back to using the sequence protocol [ and ]. Objects that support the sequence protocol should only provide if they can provide an implementation that is more efficient than the one provided by
The membership test operators [ and ] are normally implemented as an iteration through a container. However, container objects can supply the following special method with a more efficient implementation, which also does not require the object be iterable
object. __contains__[self , item]Called to implement membership test operators. Should return true if item is in self, false otherwise. For mapping objects, this should consider the keys of the mapping rather than the values or the key-item pairs
For objects that don’t define , the membership test first tries iteration via , then the old sequence iteration protocol via , see
3. 3. 8. Emulating numeric types
The following methods can be defined to emulate numeric objects. Methods corresponding to operations that are not supported by the particular kind of number implemented [e. g. , bitwise operations for non-integral numbers] should be left undefined
object. __add__[self , other]object. __sub__[self , other]object. __mul__[self , other]object. __matmul__[self , other]object. __truediv__[bản thân , khác . ]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]These methods are called to implement the binary arithmetic operations [
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]71,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]72,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]73,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]74,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]75,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]76,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]77, , ,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]80,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]81,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]82,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]83,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]84,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]85]. For instance, to evaluate the expression
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]86, where x is an instance of a class that has an method,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]88 is called. The method should be the equivalent to using and ; it should not be related to . Note that should be defined to accept an optional third argument if the ternary version of the built-in function is to be supported
If one of those methods does not support the operation with the supplied arguments, it should return
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']9object. __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]
These methods are called to implement the binary arithmetic operations [
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]71,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]72,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]73,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]74,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]75,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]76,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]77, , ,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]80,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]81,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]82,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]83,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]84,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]85] with reflected [swapped] operands. These functions are only called if the left operand does not support the corresponding operation and the operands are of different types. For instance, to evaluate the expression
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]11, where y is an instance of a class that has an method,
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]13 is called if
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]14 returns NotImplemented
Note that ternary will not try calling [the coercion rules would become too complicated]
Ghi chú
If the right operand’s type is a subclass of the left operand’s type and that subclass provides a different implementation of the reflected method for the operation, this method will be called before the left operand’s non-reflected method. This behavior allows subclasses to override their ancestors’ operations
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__[bản thân , khác . ]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]These methods are called to implement the augmented arithmetic assignments [
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]17,
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]18,
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]19,
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]20,
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]21,
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]22,
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]23,
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]24,
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]25,
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]26,
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]27,
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]28,
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]29]. These methods should attempt to do the operation in-place [modifying self] and return the result [which could be, but does not have to be, self]. If a specific method is not defined, the augmented assignment falls back to the normal methods. For instance, if x is an instance of a class with an method,
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]31 is equivalent to
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]32 . Otherwise,
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]33 and
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]34 are considered, as with the evaluation of
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]86. In certain situations, augmented assignment can result in unexpected errors [see ], but this behavior is in fact part of the data modelobject. __neg__[self]object. __pos__[bản thân]đối tượng. __abs__[bản thân]đối tượng. __invert__[self]
Called to implement the unary arithmetic operations [
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]72,
>>> # list has class "type" as its metaclass, like most classes: >>> type[list] >>> type[dict] == type[list] == type[tuple] == type[str] == type[bytes] True >>> # "list[int]" calls "list.__class_getitem__[int]" >>> list[int] list[int] >>> # list.__class_getitem__ returns a GenericAlias object: >>> type[list[int]]71, and
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]39]object. __complex__[self]object. __int__[self]object. __float__[self]
Called to implement the built-in functions , and . Should return a value of the appropriate type
object. __index__[self]Called to implement , and whenever Python needs to losslessly convert the numeric object to an integer object [such as in slicing, or in the built-in , and functions]. 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. Must return an integer
If , and are not defined then corresponding built-in functions , and fall back to
object. __round__[self[ , ndigits]]object. __trunc__[self]object. __floor__[self]object. __ceil__[self]Called to implement the built-in function and functions , and . Unless ndigits is passed to
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]59 all these methods should return the value of the object truncated to an [typically an ]
The built-in function falls back to if neither nor is defined
Changed in version 3. 11. The delegation of to is deprecated.
3. 3. 9. With Statement Context Managers
A context manager is an object that defines the runtime context to be established when executing a statement. The context manager handles the entry into, and the exit from, the desired runtime context for the execution of the block of code. Context managers are normally invoked using the
class Philosopher: def __init_subclass__[cls, /, default_name, **kwargs]: super[].__init_subclass__[**kwargs] cls.default_name = default_name class AustralianPhilosopher[Philosopher, default_name="Bruce"]: pass8 statement [described in section ], but can also be used by directly invoking their methods
Typical uses of context managers include saving and restoring various kinds of global state, locking and unlocking resources, closing opened files, etc
For more information on context managers, see
object. __enter__[self]Enter the runtime context related to this object. The statement will bind this method’s return value to the target[s] specified in the
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]71 clause of the statement, if anyobject. __exit__[self , exc_type , exc_value , traceback]
Exit the runtime context related to this object. The parameters describe the exception that caused the context to be exited. If the context was exited without an exception, all three arguments will be
If an exception is supplied, and the method wishes to suppress the exception [i. e. , prevent it from being propagated], it should return a true value. Otherwise, the exception will be processed normally upon exit from this method
Note that methods should not reraise the passed-in exception; this is the caller’s responsibility
Xem thêm
PEP 343 - The “with” statementThe specification, background, and examples for the Python statement
3. 3. 10. Customizing positional arguments in class pattern matching
When using a class name in a pattern, positional arguments in the pattern are not allowed by default, i. e.
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]75 is typically invalid without special support in
class Meta[type]: pass class MyClass[metaclass=Meta]: pass class MySubclass[MyClass]: pass98. To be able to use that kind of pattern, the class needs to define a __match_args__ attributeobject. __match_args__
This class variable can be assigned a tuple of strings. When this class is used in a class pattern with positional arguments, each positional argument will be converted into a keyword argument, using the corresponding value in __match_args__ as the keyword. The absence of this attribute is equivalent to setting it to
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]77
For example, if
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]78 is
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]79 that means that
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]75 is equivalent to
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]81. Note that the number of arguments in the pattern must be smaller than or equal to the number of elements in __match_args__; if it is larger, the pattern match attempt will raise a
New in version 3. 10
Xem thêm
PEP 634 - Structural Pattern MatchingThe specification for the Python
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]83 statement
3. 3. 11. Special method lookup
For custom classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary. That behaviour is the reason why the following code raises an exception
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule1
The rationale behind this behaviour lies with a number of special methods such as and that are implemented by all objects, including type objects. If the implicit lookup of these methods used the conventional lookup process, they would fail when invoked on the type object itself
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule2
Incorrectly attempting to invoke an unbound method of a class in this way is sometimes referred to as ‘metaclass confusion’, and is avoided by bypassing the instance when looking up special methods
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule3
In addition to bypassing any instance attributes in the interest of correctness, implicit special method lookup generally also bypasses the method even of the object’s metaclass
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule4
Bypassing the machinery in this fashion provides significant scope for speed optimisations within the interpreter, at the cost of some flexibility in the handling of special methods [the special method must be set on the class object itself in order to be consistently invoked by the interpreter]
3. 4. Coroutines
3. 4. 1. Awaitable Objects
An object generally implements an method. returned from functions are awaitable
Ghi chú
The objects returned from generators decorated with are also awaitable, but they do not implement
object. __await__[self]Phải trả lại một. Should be used to implement objects. For instance, implements this method to be compatible with the expression
Ghi chú
The language doesn’t place any restriction on the type or value of the objects yielded by the iterator returned by
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]94, as this is specific to the implementation of the asynchronous execution framework [e. g. ] that will be managing the object
New in version 3. 5
Xem thêm
PEP 492 for additional information about awaitable objects
3. 4. 2. Coroutine Objects
are objects. A coroutine’s execution can be controlled by calling and iterating over the result. When the coroutine has finished executing and returns, the iterator raises , and the exception’s
class A: pass c = C[] A.x = c # The hook is not called c.__set_name__[A, 'x'] # Manually invoke the hook94 attribute holds the return value. If the coroutine raises an exception, it is propagated by the iterator. Coroutines should not directly raise unhandled exceptions
Coroutines also have the methods listed below, which are analogous to those of generators [see ]. However, unlike generators, coroutines do not directly support iteration
Changed in version 3. 5. 2. It is a to await on a coroutine more than once.
coroutine. send[value]Starts or resumes execution of the coroutine. If value is
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8, this is equivalent to advancing the iterator returned by . If value is not
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8, this method delegates to the method of the iterator that caused the coroutine to suspend. The result [return value, , or other exception] is the same as when iterating over the
>>> from enum import Enum >>> class Menu[Enum]: .. """A breakfast menu""" .. SPAM = 'spam' .. BACON = 'bacon' ... >>> # Enum classes have a custom metaclass: >>> type[Menu] >>> # EnumMeta defines __getitem__, >>> # so __class_getitem__ is not called, >>> # and the result is not a GenericAlias object: >>> Menu['SPAM'] >>> type[Menu['SPAM']]88 return value, described abovecoroutine. throw[value]coroutine. throw[type[ , value[ , traceback]]]
Raises the specified exception in the coroutine. This method delegates to the method of the iterator that caused the coroutine to suspend, if it has such a method. Otherwise, the exception is raised at the suspension point. The result [return value, , or other exception] is the same as when iterating over the return value, described above. If the exception is not caught in the coroutine, it propagates back to the caller
coroutine. close[]Causes the coroutine to clean itself up and exit. If the coroutine is suspended, this method first delegates to the method of the iterator that caused the coroutine to suspend, if it has such a method. Then it raises at the suspension point, causing the coroutine to immediately clean itself up. Finally, the coroutine is marked as having finished executing, even if it was never started
Coroutine objects are automatically closed using the above process when they are about to be destroyed
3. 4. 3. Asynchronous Iterators
An asynchronous iterator can call asynchronous code in its
a[1:2] = b12 method
Asynchronous iterators can be used in an statement
object. __aiter__[self]Must return an asynchronous iterator object
object. __anext__[self]Must return an awaitable resulting in a next value of the iterator. Should raise a error when the iteration is over
An example of an asynchronous iterable object
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule5
New in version 3. 5
Changed in version 3. 7. Prior to Python 3. 7, could return an awaitable that would resolve to an .
Starting with Python 3. 7, must return an asynchronous iterator object. Returning anything else will result in a error
3. 4. 4. Asynchronous Context Managers
Trình quản lý ngữ cảnh không đồng bộ là trình quản lý ngữ cảnh có khả năng tạm dừng thực thi trong các phương thức
a[1:2] = b18 và
a[1:2] = b19 của nó
Asynchronous context managers can be used in an statement
đối tượng. __aenter__[self]Semantically similar to , the only difference being that it must return an awaitable
object. __aexit__[bản thân , exc_type, exc_value, traceback]Semantically similar to , the only difference being that it must return an awaitable
An example of an asynchronous context manager class
import sys from types import ModuleType class VerboseModule[ModuleType]: def __repr__[self]: return f'Verbose {self.__name__}' def __setattr__[self, attr, value]: print[f'Setting {attr}...'] super[].__setattr__[attr, value] sys.modules[__name__].__class__ = VerboseModule6
New in version 3. 5
Footnotes
Trong một số trường hợp, có thể thay đổi loại đối tượng, trong các điều kiện được kiểm soát nhất định. It generally isn’t a good idea though, since it can lead to some very strange behaviour if it is handled incorrectly
The , , , and methods have special handling for this; others will still raise a , but may do so by relying on the behavior that
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8 is not callable
“Does not support” here means that the class has no such method, or the method returns
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']9. Do not set the method to
class A: x = C[] # Automatically calls: x.__set_name__[A, 'x']8 if you want to force fallback to the right operand’s reflected method—that will instead have the opposite effect of explicitly blocking such fallback
For operands of the same type, it is assumed that if the non-reflected method – such as – fails then the overall operation is not supported, which is why the reflected method is not called