"abc" --- 抽象基底類別
**********************

**原始碼：**Lib/abc.py

======================================================================

如同在 **PEP 3119** 中所述，該模組提供了在 Python 中定義*抽象基底類別*
(ABC) 的基礎元件；若想瞭解為什麼需要在 Python 中增加這個模組，請見 PEP
文件。（也請見 **PEP 3141** 以及 "numbers" 模組以瞭解基於 ABC 的數字型
別階層關係。）

"collections" 模組中有一些衍生自 ABC 的具體類別；當然這些類別還可以進
一步衍生出其他類別。此外，"collections.abc" 子模組中有一些 ABC 可被用
於測試一個類別或實例是否提供特定介面，例如它是否*可雜湊 (hashable)* 或
它是否為*對映*。

該模組提供了一個用來定義 ABC 的元類別 (metaclass) "ABCMeta" 和另一個以
繼承的方式定義 ABC 的工具類別 "ABC"：

class abc.ABC

   一個使用 "ABCMeta" 作為元類別的工具類別。抽象基底類別可以透過自
   "ABC" 衍生而建立，這就避免了在某些情況下會令人混淆的元類別用法，用
   法如以下範例：

      from abc import ABC

      class MyABC(ABC):
          pass

   注意 "ABC" 的型別仍然是 "ABCMeta"，因此繼承 "ABC" 仍然需要關注使用
   元類別的注意事項，如多重繼承可能會導致元類別衝突。當然你也可以傳入
   元類別關鍵字並直接使用 "ABCMeta" 來定義一個抽象基底類別，例如：

      from abc import ABCMeta

      class MyABC(metaclass=ABCMeta):
          pass

   在 3.4 版被加入.

class abc.ABCMeta

   用於定義抽象基底類別（ABC）的元類別。

   使用該元類別以建立一個 ABC。一個 ABC 可以像 mix-in 類別一樣直接被子
   類別繼承。你也可以將不相關的具體類別（甚至是內建類別）和 ABC 註冊為
   「虛擬子類別 (virtual subclass)」 —— 這些類別以及它們的子類別會被內
   建函式 "issubclass()" 識別為已註冊 ABC 的子類別，但是該 ABC 不會出
   現在其 MRO（Method Resolution Order，方法解析順序）中，由該 ABC 所
   定義的方法實作也不可呼叫（即使透過 "super()" 呼叫也不行）。[1]

   使用 "ABCMeta" 作為元類別建立的類別含有以下的方法：

   register(subclass)

      將*子類別*註冊為該 ABC 的「抽象子類別」，例如：

         from abc import ABC

         class MyABC(ABC):
             pass

         MyABC.register(tuple)

         assert issubclass(tuple, MyABC)
         assert isinstance((), MyABC)

      在 3.3 版的變更: 回傳已註冊的子類別，使其能夠作為類別裝飾器。

      在 3.4 版的變更: 你可以使用 "get_cache_token()" 函式來檢測對
      "register()" 的呼叫。

   你也可以覆寫 (override) 虛擬基底類別中的這個方法：

   __subclasshook__(subclass)

      （必須定義為類別方法。）

      檢查 *subclass* 是否該被認為是該 ABC 的子類別，也就是說你可以直
      接自訂 "issubclass()" 的行為，而不用對於那些你希望定義為該 ABC
      的子類別的類別都個別呼叫 "register()" 方法。（這個類別方法是在
      ABC 的 "__subclasscheck__()" 方法中呼叫。）

      此方法必須回傳 "True"、"False" 或是 "NotImplemented"。如果回傳
      "True"，*subclass* 就會被認為是這個 ABC 的子類別。如果回傳
      "False"，*subclass* 就會被判定並非該 ABC 的子類別，即便正常情況
      應如此。如果回傳 "NotImplemented"，子類別檢查會按照正常機制繼續
      執行。

   為了對這些概念做一演示，請見以下定義 ABC 的範例：

      class Foo:
          def __getitem__(self, index):
              ...
          def __len__(self):
              ...
          def get_iterator(self):
              return iter(self)

      class MyIterable(ABC):

          @abstractmethod
          def __iter__(self):
              while False:
                  yield None

          def get_iterator(self):
              return self.__iter__()

          @classmethod
          def __subclasshook__(cls, C):
              if cls is MyIterable:
                  if any("__iter__" in B.__dict__ for B in C.__mro__):
                      return True
              return NotImplemented

      MyIterable.register(Foo)

   ABC "MyIterable" 定義了作為抽象方法的一個標準疊代方法 "__iter__()"
   。這裡給定的實作仍可在子類別中被呼叫。"get_iterator()" 方法也是
   "MyIterable" 抽象基底類別的一部分，但它不必被非抽象衍生類別覆寫。

   這裡定義的 "__subclasshook__()" 類別方法說明任何在其 "__dict__" (或
   在其透過 "__mro__" 列表存取的基底類別) 中具有 "__iter__()" 方法的類
   別也都會被視為 "MyIterable"。

   最後，即使 "Foo" 沒有定義 "__iter__()" 方法（它使用了以 "__len__()"
   和 "__getitem__()" 所定義的舊式可疊代物件協定），最末一行使其成為
   "MyIterable" 的一個虛擬子類別。請注意這不會使 "get_iterator" 成為
   "Foo" 的一個可用方法，所以它是需要被另外提供的。

"abc" 模組也提供了這些裝飾器：

@abc.abstractmethod

   用於表示抽象方法的裝飾器。

   Using this decorator requires that the class's metaclass is
   "ABCMeta" or is derived from it.  A class that has a metaclass
   derived from "ABCMeta" cannot be instantiated unless all of its
   abstract methods and properties are overridden.  The abstract
   methods can be called using any of the normal 'super' call
   mechanisms.  "@abstractmethod" may be used to declare abstract
   methods for properties and descriptors.

   Dynamically adding abstract methods to a class, or attempting to
   modify the abstraction status of a method or class once it is
   created, are only supported using the "update_abstractmethods()"
   function.  The "@abstractmethod" only affects subclasses derived
   using regular inheritance; "virtual subclasses" registered with the
   ABC's "register()" method are not affected.

   When "@abstractmethod" is applied in combination with other method
   descriptors, it should be applied as the innermost decorator, as
   shown in the following usage examples:

      class 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(self):
              ...
          @my_abstract_property.setter
          @abstractmethod
          def my_abstract_property(self, val):
              ...

          @abstractmethod
          def _get_x(self):
              ...
          @abstractmethod
          def _set_x(self, val):
              ...
          x = property(_get_x, _set_x)

   In order to correctly interoperate with the abstract base class
   machinery, the descriptor must identify itself as abstract using
   "__isabstractmethod__". In general, this attribute should be "True"
   if any of the methods used to compose the descriptor are abstract.
   For example, Python's built-in "@property" does the equivalent of:

      class Descriptor:
          ...
          @property
          def __isabstractmethod__(self):
              return any(getattr(f, '__isabstractmethod__', False) for
                         f in (self._fget, self._fset, self._fdel))

   備註:

     不同於 Java 抽象方法，這些抽象方法可能具有一個實作。這個實作可在
     覆寫它的類別上透過 "super()" 機制來呼叫。這在使用協作多重繼承
     (cooperative multiple-inheritance) 的框架中，可以被用作 super 呼
     叫的一個端點 (end-point)。

"abc" 模組還支援下列舊式裝飾器：

@abc.abstractclassmethod

   在 3.2 版被加入.

   在 3.3 版之後被棄用: It is now possible to use "@classmethod" with
   "@abstractmethod", making this decorator redundant.

   A subclass of the built-in "classmethod", indicating an abstract
   classmethod. Otherwise it is similar to "@abstractmethod".

   This special case is deprecated, as the "@classmethod" decorator is
   now correctly identified as abstract when applied to an abstract
   method:

      class C(ABC):
          @classmethod
          @abstractmethod
          def my_abstract_classmethod(cls, arg):
              ...

@abc.abstractstaticmethod

   在 3.2 版被加入.

   在 3.3 版之後被棄用: It is now possible to use "@staticmethod" with
   "@abstractmethod", making this decorator redundant.

   A subclass of the built-in "staticmethod", indicating an abstract
   staticmethod. Otherwise it is similar to "@abstractmethod".

   This special case is deprecated, as the "@staticmethod" decorator
   is now correctly identified as abstract when applied to an abstract
   method:

      class C(ABC):
          @staticmethod
          @abstractmethod
          def my_abstract_staticmethod(arg):
              ...

@abc.abstractproperty

   在 3.3 版之後被棄用: It is now possible to use "@property",
   "@property.getter", "@property.setter" and "@property.deleter" with
   "@abstractmethod", making this decorator redundant.

   A subclass of the built-in "property", indicating an abstract
   property.

   This special case is deprecated, as the "@property" decorator is
   now correctly identified as abstract when applied to an abstract
   method:

      class C(ABC):
          @property
          @abstractmethod
          def my_abstract_property(self):
              ...

   上面的例子定義了一個唯讀特性；你也可以透過適當地將一個或多個底層方
   法標記為抽象的來定義可讀寫的抽象特性：

      class C(ABC):
          @property
          def x(self):
              ...

          @x.setter
          @abstractmethod
          def x(self, val):
              ...

   如果只有某些元件是抽象的，則只需更新那些元件即可在子類別中建立具體
   的特性：

      class D(C):
          @C.x.setter
          def x(self, val):
              ...

"abc" 模組也提供了這些函式：

abc.get_cache_token()

   回傳目前 ABC 快取令牌 (cache token)。

   此令牌是一個（支援相等性測試的）不透明物件 (opaque object)，用於為
   虛擬子類別標識抽象基底類別快取的目前版本。此令牌會在任何 ABC 上每次
   呼叫 "ABCMeta.register()" 時發生更改。

   在 3.4 版被加入.

abc.update_abstractmethods(cls)

   重新計算一個抽象類別之抽象狀態的函式。如果一個類別的抽象方法在建立
   後被實作或被修改，則應當呼叫此函式。通常此函式應在一個類別裝飾器內
   部被呼叫。

   回傳 *cls*，使其能夠用作為類別的裝飾器。

   如果 *cls* 不是 "ABCMeta" 的實例則不做任何操作。

   備註:

     此函式會假定 *cls* 的超類別 (superclass) 已經被更新。它不會更新任
     何子類別。

   在 3.10 版被加入.

-[ 註腳 ]-

[1] C++ 程式設計師需要注意到 Python 中虛擬基底類別的概念和 C++ 中的並
    不相同。
