Python số nguyên 64-bit

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__ = VerboseModule
9 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"):
    pass
0

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"):
    pass
5. 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"):
    pass
9,
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à sai

Khô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 hook
3 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 hook
4. 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):
    pass
1 và
class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
2 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):
    pass
3 hoặc
class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
4 đượ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):
    pass
9 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"
        )
1

trình tự

Chúng đại diện cho các tập hợp có thứ tự hữu hạn được lập chỉ mục bởi các số không âm. Hàm tích hợp 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ến

Mộ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ây

Chuỗ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

byte

Mộ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 <= x < 256. Các ký tự byte (như

>>> 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 đổi

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

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

danh sách

Các mục của danh sách là các đối tượng Python tùy ý. Danh sách được hình thành bằng cách đặt 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 byte

Mộ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ại

Chúng đại diện cho các tập hợp hữu hạn, không có thứ tự của các đối tượng duy nhất, bất biến. Như vậy, chúng không thể được lập chỉ mục bởi bất kỳ chỉ số 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] = b
4), 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] = b
6

Frozen 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] = b
8 chọn mục được lập chỉ mục bởi
a[1:2] = b
9 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ển

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 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] = b
4) 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ĩa

Mộ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__ = VerboseModule
09

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__ = VerboseModule
13

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__ = VerboseModule
15

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__ = VerboseModule
17

Đố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__ = VerboseModule
18

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__ = VerboseModule
20

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__ = VerboseModule
22

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__ = VerboseModule
23

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__ = VerboseModule
24 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__ = VerboseModule
25

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__ = VerboseModule
22. Đ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ẩm

Mộ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__ = VerboseModule
29 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__ = VerboseModule
30 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__ = VerboseModule
29 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__ = VerboseModule
30 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__ = VerboseModule
29 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__ = VerboseModule
30 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__ = VerboseModule
30) đượ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__ = VerboseModule
29) 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__ = VerboseModule
43 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__ = VerboseModule
44 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"):
    pass
0 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__ = VerboseModule
43, 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__ = VerboseModule
47 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__ = VerboseModule
48

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__ = VerboseModule
29 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__ = VerboseModule
47 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__ = VerboseModule
51 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__ = VerboseModule
52 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__ = VerboseModule
53 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ện

Hà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__ = VerboseModule
54. 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ẵn

Mộ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__ = VerboseModule
09 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__ = VerboseModule
80, 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__ = VerboseModule
29 được đặt thành đối tượng được biểu thị bằng alist

Cá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__ = VerboseModule
82 và, trong trường hợp điển hình, để khởi tạo thể hiện mới

Trườ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ô-đun

Cá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__ = VerboseModule
18 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__ = VerboseModule
90 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__ = VerboseModule
91. Đố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__ = VerboseModule
92 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__ = VerboseModule
93

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__ = VerboseModule
09

Chuỗ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__ = VerboseModule
23

Mộ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__ = VerboseModule
23, 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ỉnh

Cá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"):
    pass
02 đượ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"):
    pass
03 (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__ = VerboseModule
43, 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__ = VerboseModule
29 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__ = VerboseModule
43. 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

tê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__ = VerboseModule
13

Tê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__ = VerboseModule
09

Chuỗ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 đị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__ = VerboseModule
23

Mộ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__ = VerboseModule
23, vui lòng xem

thể hiện lớp

Một thể hiện của lớp được tạo bằng cách gọi một đối tượng lớp (xem 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__ = VerboseModule
29 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"):
    pass
27,
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
28 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"):
    pass
29 đượ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"):
    pass
31 đư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"):
    pass
47. 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"):
    pass
49 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"):
    pass
50 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"):
    pass
51 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"):
    pass
52 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"):
    pass
53 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"):
    pass
54) 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"):
    pass
47 để 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"):
    pass
56 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"):
    pass
57 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"):
    pass
58 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"):
    pass
47 đượ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"):
    pass
41 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"):
    pass
62. 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
    
    64

  • Vị 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"):
    pass
64 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"):
    pass
71 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"):
    pass
73 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"):
    pass
79 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"):
    pass
80 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"):
    pass
81

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"):
    pass
82, 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"):
    pass
84 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"):
    pass
86 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"):
    pass
88 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ên

Cá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"):
    pass
91 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"):
    pass
92 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"):
    pass
94 để 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"):
    pass
95 đ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"):
    pass
95 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"):
    pass
79 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"):
    pass
80 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"):
    pass
94 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"):
    pass
94 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ĩnh

Cá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ớp

Một đối tượng phương thức lớp, giống như một đối tượng phương thức tĩnh, là một trình bao bọc xung quanh một đối tượng khác làm thay đổi cách truy xuất đối tượng đó từ các lớp và các thể hiện của lớp. Hành vi của các đối tượng phương thức lớp khi truy xuất như vậy được mô tả ở trên, 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"):
    pass
0 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"):
    pass
0 đ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"):
    pass
0 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"):
    pass
29. Đặ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;

đối tượng. __repr__(bản thân)

Đượ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):
    pass
1 và
class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
2 đượ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 hook
02), 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__ = VerboseModule
7, 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 hook
08. Đố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 hook
15 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 hook
31

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 hook
51

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 hook
54

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 hook
56 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 hook
51

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 hook
03; . 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 hook
68) 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 hook
72; 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 hook
85

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"):
    pass
79 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"):
    pass
80 và
class A:
   pass

c = C()
A.x = c                  # The hook is not called
c.__set_name__(A, 'x')   # Manually invoke the hook
88

đố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 hook
90

Đố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 hook
91 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"):
    pass
80,
class A:
   pass

c = C()
A.x = c                  # The hook is not called
c.__set_name__(A, 'x')   # Manually invoke the hook
88,
class A:
   pass

c = C()
A.x = c                  # The hook is not called
c.__set_name__(A, 'x')   # Manually invoke the hook
94

đối tượng. __delattr__(bản thân , tên)

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 hook
96 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 hook
97 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"):
    pass
80 và
class A:
   pass

c = C()
A.x = c                  # The hook is not called
c.__set_name__(A, 'x')   # Manually invoke the hook
88

đố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):
    pass
02 và
class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
03 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):
    pass
02 ở 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):
    pass
02 đượ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__ = VerboseModule
19 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):
    pass
03 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"):
    pass
22 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):
    pass
02 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"):
    pass
22 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):
    pass
03 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):
    pass
02 và
class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
03 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):
    pass
28 đượ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):
    pass
33 có chuỗi tra cứu bắt đầu bằng
class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
34, sau đó là
class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
35 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):
    pass
36 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):
    pass
33. Cách lập luận phụ thuộc vào
class A:
    x = C()  # Automatically calls: x.__set_name__(A, 'x')
0

Gọ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):
    pass
39

Rà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):
    pass
33 được chuyển thành cuộc gọi.
class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
41

Rà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):
    pass
42 được chuyển thành cuộc gọi.
class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
43

siê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):
    pass
44 tìm kiếm
class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
45 cho một lớp cơ sở
class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
46 theo sau
class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
47 và sau đó trả về
class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
48. 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"):
    pass
0 đượ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 hook
73, 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):
    pass
26 và/hoặc
class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
27, 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 hook
73 và
class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
26, 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 hook
73. 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 hook
73 và
class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
26 (và/hoặc
class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
27) 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

3. 3. 2. 4. 1. Lưu ý khi sử dụng __slots__
  • 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):
    pass
84 solely applies to future subclasses of the class defining the method

classmethod object. __init_subclass__(cls)

Phương thức này được gọi bất cứ khi nào lớp chứa được phân lớp. cls 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):
    pass
84. For compatibility with other classes using
class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
84, 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):
    pass
87 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):
    pass
88 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):
    pass
84 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):
    pass
90

New in version 3. 6

When a class is created,

class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
91 scans the class variables and makes callbacks to those with a hook

object. __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):
    pass
96

The class creation process can be customized by passing the

class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
88 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):
    pass
98 and
class Meta(type):
    pass

class MyClass(metaclass=Meta):
    pass

class MySubclass(MyClass):
    pass
99 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):
    pass
90) 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 hook
2

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 hook
25

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 3000

Introduced 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"):
    pass
22 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"):
    pass
22 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"):
    pass
22 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"):
    pass
22 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

  1. 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;

  2. 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;

  3. 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 super

Describes 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"):
    pass
22 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"
        )
43

class. __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 Classes

Includes 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 Hints

Introducing Python’s framework for type annotations

Documentation for objects representing parameterized generic classes

, and

Documentation 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"
        )
54

classmethod 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 chung

Giớ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 values

object. __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 method

object. __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__ = VerboseModule
0

and so forth. Missing slice items are always filled in with

class A:
    x = C()  # Automatically calls: x.__set_name__(A, 'x')
8

object. __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 details

object. __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 method

object. __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 method

object. __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 dictionary

object. __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')
9

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

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 model

object. __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"):
    pass
8 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 any

object. __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” statement

The 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):
    pass
98. To be able to use that kind of pattern, the class needs to define a __match_args__ attribute

object. __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 Matching

The 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__ = VerboseModule
1

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__ = VerboseModule
2

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__ = VerboseModule
3

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__ = VerboseModule
4

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 hook
94 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 above

coroutine. 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] = b
12 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__ = VerboseModule
5

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] = b
18 và
a[1:2] = b
19 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__ = VerboseModule
6

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