abc --- Các lớp cơ sở trừu tượng¶
Source code: Lib/abc.py
Mô-đun này cung cấp cơ sở hạ tầng để xác định abstract base classes (ABC) trong Python, như được nêu trong PEP 3119; xem PEP để biết lý do tại sao điều này được thêm vào Python. (Xem thêm PEP 3141 và mô-đun numbers về phân cấp loại cho các số dựa trên ABC.)
Mô-đun collections có một số lớp cụ thể xuất phát từ ABC; tất nhiên những điều này có thể được rút ra thêm. Ngoài ra, mô-đun con collections.abc có một số ABC có thể được sử dụng để kiểm tra xem một lớp hoặc phiên bản có cung cấp một giao diện cụ thể hay không, chẳng hạn như đó là hashable hay mapping.
Mô-đun này cung cấp siêu dữ liệu ABCMeta để xác định ABC và lớp trợ giúp ABC để xác định ABC thông qua tính kế thừa:
- class abc.ABC¶
Một lớp trợ giúp có siêu dữ liệu là
ABCMeta. Với lớp này, một lớp cơ sở trừu tượng có thể được tạo bằng cách bắt nguồn từABCđể tránh việc sử dụng siêu dữ liệu đôi khi gây nhầm lẫn, ví dụ:từ abc nhập ABC lớp MyABC(ABC): vượt qua
Lưu ý rằng loại
ABCvẫn làABCMeta, do đó việc kế thừa từABCyêu cầu các biện pháp phòng ngừa thông thường liên quan đến việc sử dụng siêu dữ liệu, vì nhiều kế thừa có thể dẫn đến xung đột siêu dữ liệu. Người ta cũng có thể định nghĩa một lớp cơ sở trừu tượng bằng cách chuyển từ khóa metaclass và sử dụng trực tiếpABCMeta, ví dụ:từ abc nhập ABCMeta lớp MyABC(metaclass=ABCMeta): vượt qua
Added in version 3.4.
- class abc.ABCMeta¶
Siêu dữ liệu để xác định các Lớp cơ sở trừu tượng (ABC).
Sử dụng siêu dữ liệu này để tạo ABC. Một ABC có thể được phân lớp trực tiếp và sau đó hoạt động như một lớp hỗn hợp. Bạn cũng có thể đăng ký các lớp cụ thể không liên quan (thậm chí các lớp dựng sẵn) và các ABC không liên quan làm "lớp con ảo" -- những lớp này và lớp con của chúng sẽ được coi là lớp con của việc đăng ký ABC bởi hàm
issubclass()tích hợp, nhưng việc đăng ký ABC sẽ không hiển thị trong MRO (Thứ tự phân giải phương thức) của chúng cũng như việc triển khai phương thức được xác định bởi ABC đăng ký sẽ không thể gọi được (thậm chí không thông quasuper()). [1]Các lớp được tạo bằng siêu dữ liệu
ABCMetacó phương thức sau:- register(subclass)¶
Đăng ký subclass làm "lớp con ảo" của ABC này. Ví dụ:
từ abc nhập ABC lớp MyABC(ABC): vượt qua MyABC.register(tuple) khẳng định issubclass(tuple, MyABC) khẳng định isinstance((), MyABC)
Thay đổi trong phiên bản 3.3: Trả về lớp con đã đăng ký, để cho phép sử dụng như một công cụ trang trí lớp.
Thay đổi trong phiên bản 3.4: Để phát hiện các cuộc gọi đến
register(), bạn có thể sử dụng chức năngget_cache_token().
Bạn cũng có thể ghi đè phương thức này trong lớp cơ sở trừu tượng:
- __subclasshook__(subclass)¶
(Phải được định nghĩa là một phương thức lớp.)
Kiểm tra xem subclass có được coi là lớp con của ABC này hay không. Điều này có nghĩa là bạn có thể tùy chỉnh thêm hành vi của
issubclass()mà không cần phải gọiregister()trên mỗi lớp mà bạn muốn coi là lớp con của ABC. (Phương thức lớp này được gọi từ phương thức__subclasscheck__()của ABC.)Phương thức này sẽ trả về
True,FalsehoặcNotImplemented. Nếu nó trả vềTruethì subclass được coi là lớp con của ABC này. Nếu nó trả vềFalse, subclass không được coi là lớp con của ABC này, ngay cả khi nó thường là một lớp con. Nếu nó trả vềNotImplemented, việc kiểm tra lớp con sẽ được tiếp tục với cơ chế thông thường.
Để minh họa các khái niệm này, hãy xem ví dụ này về định nghĩa ABC:
lớp Foo: def __getitem__(tự, chỉ mục): ... chắc chắn __len__(tự): ... def get_iterator(self): trả về iter(self) lớp MyIterable(ABC): @abstractmethod chắc chắn __iter__(tự): trong khi sai: năng suất Không có def get_iterator(self): tự trả về.__iter__() @classmethod def __subclasshook__(cls, C): nếu cls là MyIterable: nếu có("__iter__" trong B.__dict__ cho B trong C.__mro__): trả về Đúng trả về Chưa thực hiện MyIterable.register(Foo)
ABC
MyIterableđịnh nghĩa phương thức lặp tiêu chuẩn,__iter__(), là một phương thức trừu tượng. Việc triển khai được đưa ra ở đây vẫn có thể được gọi từ các lớp con. Phương thứcget_iterator()cũng là một phần của lớp cơ sở trừu tượngMyIterable, nhưng nó không bị ghi đè trong các lớp dẫn xuất không trừu tượng.Phương thức lớp
__subclasshook__()được định nghĩa ở đây cho biết rằng bất kỳ lớp nào có phương thức__iter__()trong__dict__của nó (hoặc trong một trong các lớp cơ sở của nó, được truy cập thông qua danh sách__mro__) cũng được coi làMyIterable.Cuối cùng, dòng cuối cùng biến
Foothành một lớp con ảo củaMyIterable, mặc dù nó không định nghĩa phương thức__iter__()(nó sử dụng giao thức lặp kiểu cũ, được định nghĩa theo__len__()và__getitem__()). Lưu ý rằng điều này sẽ không cung cấpget_iteratornhư một phương thức củaFoo, vì vậy nó được cung cấp riêng.
Mô-đun abc cũng cung cấp công cụ trang trí sau:
- @abc.abstractmethod¶
Một trang trí chỉ ra các phương pháp trừu tượng.
Việc sử dụng trình trang trí này yêu cầu siêu dữ liệu của lớp là
ABCMetahoặc bắt nguồn từ siêu dữ liệu đó. Một lớp có siêu dữ liệu bắt nguồn từABCMetakhông thể được khởi tạo trừ khi tất cả các phương thức và thuộc tính trừu tượng của nó bị ghi đè. Các phương thức trừu tượng có thể được gọi bằng cách sử dụng bất kỳ cơ chế gọi 'siêu' thông thường nào.abstractmethod()có thể được sử dụng để khai báo các phương thức trừu tượng cho các thuộc tính và bộ mô tả.Việc thêm động các phương thức trừu tượng vào một lớp hoặc cố gắng sửa đổi trạng thái trừu tượng của một phương thức hoặc lớp sau khi nó được tạo chỉ được hỗ trợ bằng cách sử dụng hàm
update_abstractmethods(). Zz001zz chỉ ảnh hưởng đến các lớp con được dẫn xuất bằng cách sử dụng tính kế thừa thông thường; "Các lớp con ảo" được đăng ký bằng phương thứcregister()của ABC không bị ảnh hưởng.Khi
abstractmethod()được áp dụng kết hợp với các bộ mô tả phương thức khác, nó sẽ được áp dụng làm phần trang trí trong cùng, như trong các ví dụ sử dụng sau:lớp C (ABC): @abstractmethod def my_abstract_method(self, arg1): ... @classmethod @abstractmethod def my_abstract_classmethod(cls, arg2): ... @staticmethod @abstractmethod def my_abstract_staticmethod(arg3): ... @property @abstractmethod def my_abstract_property(tự): ... @my_abstract_property.setter @abstractmethod def my_abstract_property(self, val): ... @abstractmethod def _get_x(tự): ... @abstractmethod def _set_x(tự, val): ... x = thuộc tính(_get_x, _set_x)
Để tương tác chính xác với máy móc lớp cơ sở trừu tượng, bộ mô tả phải tự xác định là trừu tượng bằng cách sử dụng
__isabstractmethod__. Nói chung, thuộc tính này phải làTruenếu bất kỳ phương thức nào được sử dụng để soạn thảo bộ mô tả là trừu tượng. Ví dụ:propertytích hợp của Python thực hiện tương đương vớiMô tả lớp: ... @property def __isabstractmethod__(self): trả về bất kỳ(getattr(f, '__isabstractmethod__', False) cho f trong (self._fget, self._fset, self._fdel))
Ghi chú
Không giống như các phương thức trừu tượng của Java, các phương thức trừu tượng này có thể được triển khai. Việc triển khai này có thể được gọi thông qua cơ chế
super()từ lớp ghi đè nó. Điều này có thể hữu ích như một điểm cuối cho một siêu lệnh gọi trong một khung sử dụng tính năng đa kế thừa hợp tác.
Mô-đun abc cũng hỗ trợ các trình trang trí cũ sau:
- @abc.abstractclassmethod¶
Added in version 3.2.
Sắp loại bỏ từ phiên bản 3.3: Hiện tại có thể sử dụng
classmethodvớiabstractmethod(), khiến công cụ trang trí này trở nên dư thừa.Một lớp con của
classmethod()tích hợp sẵn, biểu thị một phương thức lớp trừu tượng. Nếu không thì nó tương tự nhưabstractmethod().Trường hợp đặc biệt này không được dùng nữa vì trình trang trí
classmethod()hiện được xác định chính xác là trừu tượng khi áp dụng cho một phương thức trừu tượnglớp C (ABC): @classmethod @abstractmethod def my_abstract_classmethod(cls, arg): ...
- @abc.abstractstaticmethod¶
Added in version 3.2.
Sắp loại bỏ từ phiên bản 3.3: Hiện tại có thể sử dụng
staticmethodvớiabstractmethod(), khiến công cụ trang trí này trở nên dư thừa.Một lớp con của
staticmethod()tích hợp, biểu thị một phương thức tĩnh trừu tượng. Nếu không thì nó tương tự nhưabstractmethod().Trường hợp đặc biệt này không được dùng nữa vì trình trang trí
staticmethod()hiện được xác định chính xác là trừu tượng khi áp dụng cho một phương thức trừu tượnglớp C (ABC): @staticmethod @abstractmethod def my_abstract_staticmethod(arg): ...
- @abc.abstractproperty¶
Sắp loại bỏ từ phiên bản 3.3: Hiện tại có thể sử dụng
property,property.getter(),property.setter()vàproperty.deleter()vớiabstractmethod(), khiến công cụ trang trí này trở nên dư thừa.Một lớp con của
property()tích hợp, biểu thị một thuộc tính trừu tượng.Trường hợp đặc biệt này không được dùng nữa vì trình trang trí
property()hiện được xác định chính xác là trừu tượng khi áp dụng cho một phương thức trừu tượnglớp C (ABC): @property @abstractmethod def my_abstract_property(tự): ...
Ví dụ trên định nghĩa thuộc tính chỉ đọc; bạn cũng có thể xác định thuộc tính trừu tượng đọc-ghi bằng cách đánh dấu thích hợp một hoặc nhiều phương thức cơ bản là trừu tượng:
lớp C (ABC): @property def x(tự): ... @x.setter @abstractmethod def x(tự, val): ...
Nếu chỉ một số thành phần là trừu tượng thì chỉ những thành phần đó mới cần được cập nhật để tạo thuộc tính cụ thể trong lớp con:
lớp D (C): @C.x.setter def x(tự, val): ...
Mô-đun abc cũng cung cấp các chức năng sau:
- abc.get_cache_token()¶
Trả về mã thông báo bộ đệm của lớp cơ sở trừu tượng hiện tại.
Mã thông báo là một đối tượng mờ (hỗ trợ kiểm tra tính bằng nhau) xác định phiên bản hiện tại của bộ đệm lớp cơ sở trừu tượng cho các lớp con ảo. Mã thông báo thay đổi sau mỗi lệnh gọi tới
ABCMeta.register()trên bất kỳ ABC nào.Added in version 3.4.
- abc.update_abstractmethods(cls)¶
Một hàm để tính toán lại trạng thái trừu tượng của một lớp trừu tượng. Hàm này sẽ được gọi nếu các phương thức trừu tượng của một lớp đã được triển khai hoặc thay đổi sau khi nó được tạo. Thông thường, hàm này nên được gọi từ bên trong trình trang trí lớp.
Trả về cls, để cho phép sử dụng như một công cụ trang trí lớp.
Nếu cls không phải là một phiên bản của
ABCMetathì không làm gì cả.Ghi chú
Hàm này giả định rằng các siêu lớp của cls đã được cập nhật. Nó không cập nhật bất kỳ lớp con nào.
Added in version 3.10.
Chú thích cuối trang