专栏首页python3Python中接口定义和依赖注入

Python中接口定义和依赖注入

首先,我们必须明确的一点是: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中有大量使用

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Python基础之(八)类

    当类中变量引用的是可变对象是,类属性和实例属性都能直接修改这个对象,从而影响另一方的值。

    py3study
  • python3学习之对象

    py3study
  • Python 03

    py3study
  • Python基础之(八)类

    当类中变量引用的是可变对象是,类属性和实例属性都能直接修改这个对象,从而影响另一方的值。

    py3study
  • python面向对象反射-框架原理-动态导入-元类-自定义类-单例模式-项目的生命周期-05

    ​ 反射其实就是对属性的增删改查,但是如果直接使用内置的__dict__来写,语法繁琐,不好理解;另一个主要问题是,如果对象不是自己写的,而是另一方提供的,我就...

    suwanbin
  • Python之面向对象二

    面向对象的三大特性: 继承 继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类 pyt...

    新人小试
  • 8.python面向对象编程

    基本概念 Class 类 一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型。在类中定义了这些对象的都具备的属性(variables(data))、共同的方法...

    zhang_derek
  • Python多态

    多态:同类对象的多种形态,一个接口多种实现,(以封装和继承为前提),不同的子类调用相同的方法,产生不同的结果

    橙子探索测试
  • 10 . Python之面向对象

    类中的方法一般都是通过对象执行的(除去类方法,静态方法外),并且对象执行这些方法都会自动将对象空间传给方法中的第一个参数self

    常见_youmen
  • Python 03

    py3study

扫码关注云+社区

领取腾讯云代金券