python中的接口和依赖注入
首先,我们必须明确的一点是: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' ) b = Bar() b.f1() b.f2() b.f3() |
依赖注入
首先我们先看一个普通的类:
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 | class MyType( type ): def __call__( cls , * args, * * kwargs): obj = cls .__new__( cls , * args, * * kwargs) print ( '在这里面..' ) print ( '==========================' ) print ( '来咬我呀' ) obj.__init__( * args, * * kwargs) return obj class Foo(metaclass = MyType): def __init__( self ): self .name = 'alex' f = Foo() print (f.name) |
如果要熟练应用依赖注入,我还要弄懂一个概念,那就是组合:组合的目的就是解耦,减少依赖性,原来以某个具体的值或对象传入到内部改成以参数的形式传入
比如:在实例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) |
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步