文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Python中接口定义和依赖注入

2023-01-31 02:41

关注

首先,我们必须明确的一点是: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 = (1, 3, 11, 45)): # 可以不用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 = (1, 3, 11, 45)):  
  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)
阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯