Python中接口定义和依赖注入

本文探讨了 Python 中的接口实现方式,包括抽象基类和第三方库 zope.interface 的使用,并介绍了依赖注入的概念及其实现方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先,我们必须明确的一点是: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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值