一 归一化设计
归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合——就好象linux的泛文件概念一样,所有东西都可以当文件处理,不必关心它是内存、磁盘、网络还是屏幕(当然,对底层设计者,当然也可以区分出“字符设备”和“块设备”,然后做出针对性的设计:细致到什么程度,视需求而定)。
class Applepay: def pay(self,money): print('Applepay支付%s'%money) class Alipay: def pay(self,money): print('Alipay支付%s'%money) ap=Applepay() al=Alipay() # ap.pay(100) # a1.pay(100) def pay(x,money): x.pay(money) pay(ap,100) pay(al,100)
这个例子是类的上面一层加了一层函数,函数硬性的调用pay动态属性。简单的实现了归一化。
二 abc模块
python本身不支持抽象类和接口类,要想实现,需要截止abc模块。abc模块是abstract base class(抽象基类) 的缩写。
ABC(抽象基类),主要定义了基本类和最基本的抽象方法。
metaclass是“类的类”,即元类。秉承Python“一切皆对象”的理念,Python中的类也是一类对象,metaclass的实例就是类(class)。
abc模块,python对于abc模块的支持,定义了一个特殊的metaclass——ABCMeta,还有一些装饰器,@abstractmethod,@abstractproperty
abc.ABCMeta,是一个metaclass,用于在python程序中创建抽象基类。
metaclass为abc.ABCMeta的抽象基类如果想要声明抽象方法,可以使用abc模块中的装饰器@abstractmethod,如果想声明抽象属性,可以使用装饰器@abstractproperty。
实例:
from abc import abstractmethod,ABCMeta class Pay(metaclass=ABCMeta): #称为接口类,最好不实现具体的方法,推荐多继承。 @abstractmethod def pay(self): pass class Applepay(Pay): def pay(self,money): print('Applepay支付%s'%money) class Alipay(Pay): def pay(self,money): print('Alipay支付%s'%money) pass ap=Applepay() al=Alipay()
继承了Pay抽象基类的Applepay,Alipay,必须实现其抽象方法pay。
PS
依赖倒置原则
A.高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。
import abc class Animal(metaclass=abc.ABCMeta): @abc.abstractmethod def talk(self): pass class People(Animal): def talk(self): print('说说话') class Dog(Animal): def talk(self): print('哼哼哼') alex=People() egon=Dog() # alex.talk() # egon.talk() def talk(x): x.talk() talk(alex) talk(egon)
talk函数和len函数一样,此时并不需要过多关注传入数据的类型。
传入的类只要是animal的子类,无需知道传入的确切的类型,都可以放心的调用talk方法,具体调用时talk方法是作用在animal还是dog还是people上,由执行时该对象的确切类型决定,这就是多态真正的威力:只管调用,而不管细节。这也是‘开闭’原则。
对扩展开放:新增animal子类都可以执行
对修改封闭:不需要修改talk函数。
六 object与type
class A: pass print(A.__bases__) print(type(A)) print(type(list))
输出:
(<class 'object'>,) <class 'type'> <class 'type'>
object是所有类的基类。type是所有类的类型。
元类——>metaclass
import abc class A(metaclass=abc.ABCMeta): pass print(A.__bases__) print(type(A))
输出:
(<class 'object'>,) <class 'abc.ABCMeta'>