程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Python >> python面對對象編程---------6:抽象基類

python面對對象編程---------6:抽象基類

編輯:Python

 抽象基本類的幾大特點:

    1:要定義但是並不完整的實現所有方法
2:基本的意思是作為父類
3:父類需要明確表示出那些方法的特征,這樣在寫子類時更加簡單明白

用抽象基本類的地方:
1:用作父類
2:用作檢驗實例類型
3:用作拋出異常說明

關於抽象基本類的幾點說明:
1:LSP(裡式替換原則):
子類必須能夠替換他們的基類型,替換後軟件運行形態不變,覺察不出基類和子類的區別。
這樣來檢驗該設計是否合理或者藏有缺陷。(從抽象類繼承而不是具體類)

2:關於isinstance的使用:
首先:大量的isinstance檢測會造成復雜而緩慢的程序還表明多態設計不好
其次:在使用isinstance時更加pythonic的用法是處理錯誤而不是請求許可
1:請求許可:
assert isinstance( some_argument, collections.abc.Container ),"{0!r} not a Container".format(some_argument)
盡管很簡潔,但是有兩個缺點: assertions can be silenced, and it would probably be better to raise a TypeError for this:
if not isinstance(some_argument, collections.abc.Container):
raise TypeError( "{0!r} not a Container".format(some_argument))
2:處理異常
try:
found = value in some_argument
except TypeError:
if not isinstance(some_argument, collections.abc.Container):
warnings.warn( "{0!r} not a Container".format(some_argument) )
raise

3:Containers and collections
container(容器),既是其可以包含多個對象,其實是多個reference的集合的概念,python內置的containers有比如list,map,set.
    collections是python內建的一個集合模塊,提供了許多可用的集合類,如namedtuple,deque,defalutdict等等。
總結:container是一個抽象類而collections是繼承了container並實現了多種子類數據結構如namedtuple,deque,chainmap,counter,ordereddict,defaultdict的類的統稱

container應該實現的:
Lower-level features include Container, Iterable, and Sized.
they require a few specific methods, particularly __contains__(), __iter__(), and __len__(), respectively

collections應該實現的:
Sequence and MutableSequence: These are the abstractions of the concrete classes list and tuple. Concrete sequence implementations also include bytes and str.
          MutableMapping: This is the abstraction of dict. It extends Mapping, but there's no built-in concrete implementation of this.
          Set and MutableSet: These are the abstractions of the concrete classes,frozenset and set.
   This allows us to build new classes or extend existing classes and maintain a clear and formal integration with the rest of Python's built-in features.

python中兩大抽象基類:
  1:各種數據類型相關的collections.abc

    >>> abs(3)
    3
    >>> isinstance(abs, collections.abc.Callable)
    True

    >>> isinstance( {}, collections.abc.Mapping )
    True
    >>> isinstance( collections.defaultdict(int), collections.abc.Mapping)
    True

  

  2:數值相關的numbers

    >>> import numbers, decimal
    >>> isinstance( 42, numbers.Number )
    True
    >>> isinstance( 355/113, numbers.Number ) #由此可見,integer和float都是number.Number類的子類
    True
    >>> issubclass( decimal.Decimal, numbers.Number ) #decimal.Decimal是numbers.Number的子類
    True
    >>> issubclass( decimal.Decimal, numbers.Integral )
    False
    >>> issubclass( decimal.Decimal, numbers.Real )
    False
    >>> issubclass( decimal.Decimal, numbers.Complex )
    False
    >>> issubclass( decimal.Decimal, numbers.Rational )
    False

來看一個簡單的抽象類
 __dict__:方法名+屬性名
 __mro__:  包含此類所有父類的元祖
 >>> class aha(list):
        def __init__(self,value):
            super().__init__(value)
 
 
 >>> a=aha('pd')
 >>> a
 ['p', 'd']
 >>> aha.__dict__
 mappingproxy({'__weakref__': <attribute '__weakref__' of 'aha' objects>, '__doc__': None, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'aha' objects>, '__init__': <function aha.__init__ at 0x030967C8>})
 >>> aha.__mro__
 (<class '__main__.aha'>, <class 'list'>, <class 'object'>)
__dict__與__mro__
 from abc import ABCMeta, abstractmethod
 class AbstractBettingStrategy(metaclass=ABCMeta):
     __slots__ = ()
     @abstractmethod
     def bet(self, hand):
         return 1
     @abstractmethod
     def record_win(self, hand):
         pass
     @abstractmethod
     def record_loss(self, hand):
         pass
     @classmethod                                #檢查了三個用抽象方法在子類中是否implement,否則報錯。
     def __subclasshook__(cls, subclass):
         if cls is Hand:
             if (any("bet" in B.__dict__ for B in subclass.__mro__) and any("record_win" in B.__dict__ for B in subclass.__mro__) and any("record_loss" in B.__dict__ for B in subclass.__mro__)):
                 return True
         return NotImplemented
 
 class Simple_Broken(AbstractBettingStrategy):
     def bet( self, hand ):
         return 1
 # The preceding code can't be built because it doesn't provide necessary implementations for all three methods.
 # The following is what happens when we try to build it:
 >>> simple= Simple_Broken()
 Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 TypeError: Can't instantiate abstract class Simple_Broken with
 abstract methods record_loss, record_win
#注,上例可能太過嚴格,有些子類並不需要實現其所有方法,這個需要具體情況再看

#注,此篇可能看起來有點不太邏輯清晰,這源於我對collections.abc以及number模塊目前還不太清晰,等改天研究明白了來改改,加些內容,此時先放出來占個位
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved