Python中接口定义和依赖注入

发布时间:2019-08-28 09:16:08编辑:auto阅读(1473)

    首先,我们必须明确的一点是:python里无接口类型,定义接口只是一个人为规定,在编程过程自我约束

    • python的类是可以写任意个方法的

    • 定义一个接口对继承类进行约束,接口里有什么方法,继承类就必须有什么方法,接口中不能任何功能代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class Interface:
         
        def f1(self):
            '''
            to do something
            :return:
            '''
     
    class Something(Interface):
         
        def f1(self):
            print('to do something...')
         
        def f2(self):
            print('to do other..')

      在其他的语言里,比如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')
     
    = Bar()
    b.f1()
    b.f2()
    b.f3()

     Python支持多继承,但是不支持接口,zope.inteface是其三方的接口实现库,在twisted中有大量使用


    1. from zope.interface import Interface  
    2. from zope.interface import implementer  
    3. import socket  
    4.   
    5. class IHostNameResolver(Interface):  
    6.     def getHostByName(name, timeout = (131145)): # 可以不用self  
    7.         """ 
    8.         Resolve the domain name C{name} into an IP address. 
    9.         """  
    10.   
    11. """ 
    12. 类装饰器等价于:implementer(IHostNameResolver)(HostNameResolver) 
    13. """  
    14. @implementer(IHostNameResolver)  
    15. class HostNameResolver:  
    16.   
    17.     def getHostByName(self, name, timeout = (131145)):  
    18.         try:  
    19.             address = socket.gethostbyname(name)  
    20.         except socket.error:  
    21.             return 'none'  
    22.         else:  
    23.             return address  
    24.   
    25. resolver = HostNameResolver()  
    26. print resolver.getHostByName('localhost')  
    27.   
    28. # 判断HostNameResolver是否实现了接口IHostNameResolver  
    29. 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__方法

    1. 在call方法里调用Foo类的__new__方法(负责创建对象)
    2. 执行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())
     
     
    = Bar()
    print(b.f)

关键字