Python高級主題:Python ABC(抽象基類)

#抽象類實例   做用統一規範接口,下降使用複雜度。
import abc
class Animal(metaclass = abc.ABCMeta): ##只能被繼承,不能實例化,實例化會報錯
@abc.abstractmethod ##加完這個方法子類必須有這個方法,不然報錯
def run(self):
pass
@abc.abstractmethod
def eat(self):
pass

class People(Animal):
def run(self):
print("People is walking")

def eat(self):
print("people is eating")

class Pig(Animal):
def run(self):
print("Pig is running")

def eat(self):
print("people is eating")

class Dog(Animal):
def run(self):
print("Dog is zouing")

def eat(self):
print("dog is eating")

peo1 = People()
pig1 = Pig()
dog1 = Dog()

peo1.run()
peo1.eat()
 
 
 
ABC,Abstract Base Class(抽象基類),主要定義了基本類和最基本的抽象方法,能夠爲子類定義共有的API,不須要具體實現。至關因而Java中的接口或者是抽象類。
    抽象基類能夠不實現具體的方法(固然也能夠實現,只不過子類若是想調用抽象基類中定義的方法須要使用super())而是將其留給派生類實現。
 
    抽象基類提供了邏輯和實現解耦的能力,即在不一樣的模塊中經過抽象基類來調用,能夠用最精簡的方式展現出代碼之間的邏輯關係,讓模塊之間的依賴清晰簡單。同時,一個抽象類能夠有多個實現,讓系統的運轉更加靈活。而針對抽象類的編程,讓每一個人能夠關注當前抽象類,只關注其方法和描述,而不須要考慮過多的其餘邏輯,這對協同開發有很大意義。極簡版的抽象類實現,也讓代碼可讀性更高。
 
    抽象基類的使用:
    1:直接繼承
        直接繼承抽象基類的子類就沒有這麼靈活,抽象基類中能夠聲明」抽象方法「和「抽象屬性」,只有徹底覆寫(實現)了抽象基類中的「抽象」內容後,才能被實例化,而虛擬子類則不受此影響。
    2:虛擬子類
    將其餘的類」註冊「到抽象基類下當虛擬子類(調用register方法),虛擬子類的好處是你實現的第三方子類不須要直接繼承自基類,能夠實現抽象基類中的部分API接口,也能夠根本不實現,可是issubclass(), issubinstance()進行判斷時仍然返回真值。
 
    Python 對於ABC的支持模塊是abc模塊,定義了一個特殊的metaclass:ABCMeta 還有一些裝飾器:@abstractmethod 和 @abstarctproperty 。abc.ABCMeta 用於在Python程序中建立抽象基類。而抽象基類若是想要聲明「抽象方法」,可使用 @abstractmethod ,若是想聲明「抽象屬性」,可使用 @abstractproperty 。
 
    爲了解決Python2&3的兼容問題,須要引入six模塊,該模塊中有一個針對類的裝飾器 @six.add_metaclass(MetaClass) 能夠爲兩個版本的Python類方便地添加metaclass
通用作法。
@six.add_metaclass(MetaClass) 的做用是在不一樣版本的Python之間提供一個優雅的聲明類的metaclass的手段,事實上不用它也能夠,只是使用了它代碼更爲整潔明瞭。
import six
 
@six.add_metaclass(Meta)
class MyClass(object):
    pass
在Python 3 等價於
import six
 
class MyClass(object, metaclass = Meta):
    pass
在Python 2.x (x >= 6)中等價於
import six
 
class MyClass(object):
    __metaclass__ = Meta
    pass
或者直接調用裝飾器,
這裏也能看出來裝飾器就是個方法包裝而已。
import six
 
class MyClass(object):
    pass
MyClass  = six.add_metaclass(Meta)(MyClass)
 
實例:
import abc
import six
 
 
@six.add_metaclass(abc.ABCMeta)
class BaseClass(object):
    @abc.abstractmethod
    def func_a(self, data):
        """
        an abstract method need to be implemented
        """
 
    @abc.abstractmethod
    def func_b(self, data):
        """
        another abstract method need to be implemented
        """
 
class SubclassImpl(BaseClass):
    def func_a(self, data):
        print("Overriding func_a, " + str(data))
 
    @staticmethod
    def func_d(self, data):
        print(type(self) + str(data))
 
class RegisteredImpl(object):
    @staticmethod
    def func_c(data):
        print("Method in third-party class, " + str(data))
BaseClass.register(RegisteredImpl)
 
 
if __name__ == '__main__':
    for subclass in BaseClass.__subclasses__():
        print("subclass of BaseClass: " + subclass.__name__)
    print("subclass do not contains RegisteredImpl")
    print("-----------------------------------------------")
 
    print("RegisteredImpl is subclass: " + str(issubclass(RegisteredImpl, BaseClass)))
    print("RegisteredImpl object  is instance: " + str(isinstance(RegisteredImpl(), BaseClass)))
    print("SubclassImpl is subclass: " + str(issubclass(SubclassImpl, BaseClass)))
 
    print("-----------------------------------------------")
    obj1 = RegisteredImpl()
    obj1.func_c("RegisteredImpl new object OK!")
    print("-----------------------------------------------")
    obj2 = SubclassImpl()  #因爲沒有實例化全部的方法,因此這裏會報錯 Can't instantiate abstract class SubclassImpl with abstract methods func_b
    obj2.func_a("It's right!")
結果以下:
subclass of BaseClass: SubclassImpl
subclass do not contains RegisteredImpl
-----------------------------------------------
RegisteredImpl is subclass: True
RegisteredImpl object  is instance: True
SubclassImpl is subclass: True
-----------------------------------------------
Method in third-party class, RegisteredImpl new object OK!
-----------------------------------------------
Traceback (most recent call last):
  File "/Users/wangqi/Git/Python/scrapy_crawler_learn/test/ABCTest.py", line 51, in <module>
    obj2 = SubclassImpl()  #因爲沒有實例化全部的方法,因此這裏會報錯 Can't instantiate abstract class SubclassImpl with abstract methods func_b
TypeError: Can't instantiate abstract class SubclassImpl with abstract methods func_b
相關文章
相關標籤/搜索