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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM