首先,我们必须明确的一点是:python里无接口类型,定义接口只是一个人为规定,在编程过程自我约束
- python的类是可以写任意个方法的
- 定义一个接口对继承类进行约束,接口里有什么方法,继承类就必须有什么方法,接口中不能任何功能代码
from zope.interface import Interface
from zope.interface import implementer
import socket
class IHostNameResolver(Interface):
def getHostByName(name, timeout = (1, 3, 11, 45)): # 可以不用self
"""
Resolve the domain name C{name} into an IP address.
"""
"""
类装饰器等价于:implementer(IHostNameResolver)(HostNameResolver)
"""
@implementer(IHostNameResolver)
class HostNameResolver:
def getHostByName(self, name, timeout = (1, 3, 11, 45)):
try:
address = socket.gethostbyname(name)
except socket.error:
return 'none'
else:
return address
resolver = HostNameResolver()
print resolver.getHostByName('localhost')
# 判断HostNameResolver是否实现了接口IHostNameResolver
print IHostNameResolver.implementedBy(HostNameResolver) # True, 调用 SpecificationBasePy.implementedBy()
在其他的语言里,比如Java,继承类没有重写接口方法是会报错的,而在python里不会,就是因为python没这个类型,所以只是在我们编程过程的一个规定,以I开头的类视为接口
1 2 3 4 5 6 7 8 9 | class IOrderRepository: def fetch_one_by(self,nid): raise Exception('子类中必须实现该方法') class Something(IOrderRepository): def fet_one_by(self,nid): print('查查查数据....') |
---|
抽象类,抽象方法
- 抽象类,可以说是类和接口的混合体,既可以定义常规方法,也可以约束子类的方法(抽象方法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | import abc #抽象类 class Foo(metaclass=abc.ABCMeta): def f1(self): print('f1') #抽象方法 @abc.abstractmethod def f2(self): ''' 打印f2 ''' class Bar(Foo): def f2(self): print('f2') def f3(self): print('f3') b = Bar() b.f1() b.f2() b.f3() |
---|
Python支持多继承,但是不支持接口,zope.inteface是其三方的接口实现库,在twisted中有大量使用
- from zope.interface import Interface
- from zope.interface import implementer
- import socket
- class IHostNameResolver(Interface):
- def getHostByName(name, timeout = (1, 3, 11, 45)): # 可以不用self
- """
- Resolve the domain name C{name} into an IP address.
- """
- """
- 类装饰器等价于:implementer(IHostNameResolver)(HostNameResolver)
- """
- @implementer(IHostNameResolver)
- class HostNameResolver:
- def getHostByName(self, name, timeout = (1, 3, 11, 45)):
- try:
- address = socket.gethostbyname(name)
- except socket.error:
- return 'none'
- else:
- return address
- resolver = HostNameResolver()
- print resolver.getHostByName('localhost')
- # 判断HostNameResolver是否实现了接口IHostNameResolver
- print IHostNameResolver.implementedBy(HostNameResolver) # True, 调用 SpecificationBasePy.implementedBy()
依赖注入
首先我们先看一个普通的类:
1 2 3 4 5 6 | class Foo: def __init__(self): self.name = 'alex' def f1(self): print(self.name) |
---|
- 首先要明确的是,在python里,一切事物皆为对象
- 而所有的类都是对象,默认是由type创建
创建类的执行流程:
- 遇到class关键词,执行type的__init__方法,创建Foo类这个对象
- 遇实例化对象(obj=Foo()),执行type里的__call__方法
- 在call方法里调用Foo类的__new__方法(负责创建对象)
- 执行Foo类的__init__方法(初始化)
了解其中的原理,我们就可以在__call__里面大做文章啦
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | class MyType(type): def __call__(cls, *args, **kwargs): ##执行Type的__call__方法,这里的cls就是<__main__.Foo object at 0x001B59F0> Foo类 obj = cls.__new__(cls, *args, **kwargs) ##Foo的__new__方法 if cls == Foo1: obj.__init__(Foo()) elif cls == Foo2: obj.__init__(Foo1()) return obj class Foo(metaclass=MyType): def __init__(self, args): print('============') self.name = args def f(self): print(self.name) class Foo1(metaclass=MyType): def __init__(self, args): print('============') self.name = args def f1(self): print(self.name) class Foo2(metaclass=MyType): def __init__(self, args): print('============') self.name = args def f2(self): print(self.name) obj = Foo2() obj.f2() # <__main__.Foo1 object at 0x002DA4F0> |
---|
如果要熟练应用依赖注入,我还要弄懂一个概念,那就是组合:组合的目的就是解耦,减少依赖性,原来以某个具体的值或对象传入到内部改成以参数的形式传入
比如:在实例Bar对象时,封装Foo对象,实例Foo对象封装Head对象,就用参数的形式传入到构造方法里
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | class Mapper: #在字典里定义依赖注入关系 __mapper_relation = {} #类直接调用注册关系 @staticmethod def register(cls,value): Mapper.__mapper_relation[cls] = value @staticmethod def exist(cls): if cls in Mapper.__mapper_relation: return True return False @staticmethod def get_value(cls): return Mapper.__mapper_relation[cls] class MyType(type): def __call__(cls,*args,**kwargs): obj = cls.__new__(cls,*args,**kwargs) arg_list = list(args) if Mapper.exist(cls): value = Mapper.get_value(cls) arg_list.append(value) obj.__init__(*arg_list,**kwargs) return obj class Head: def __init__(self): self.name = 'alex' class Foo(metaclass=MyType): def __init__(self,h): self.h = h def f1(self): print(self.h) class Bar(metaclass=MyType): def __init__(self,f): self.f = f def f2(self): print(self.f) Mapper.register(Foo,Head()) Mapper.register(Bar,Foo()) b = Bar() print(b.f) |
---|