普通的例子

首先我们先看一个普通的类:

class Foo:
    def __init__(self):
        self.name = 'ryo'
     
    def f1(self):
        print(self.name)

基础知识

首先要明确的是,在python里,一切事物皆为对象

而所有的类都是对象,默认是由type创建

创建类的执行流程

  1. 遇到class关键词,执行type的 __init__ 方法,创建Foo类这个对象

  2. 遇实例化对象(obj=Foo()),执行type里的 __call__ 方法

  3. 在call方法里调用Foo类的 __new__ 方法(负责创建对象)

  4. 执行Foo类的 __init__ 方法(初始化)

在 call 中大做文章

  • IOC.py
'''
desc: 依赖注入测试案例
author: binbin.hou
'''
class MyType(type):
    def __call__(cls,*args,**kwargs):
        obj = cls.__new__(cls,*args,**kwargs)
        print('call() method called!')
        obj.__init__(*args,**kwargs)
        return obj
 
class Foo(metaclass=MyType):
    def __init__(self):
        self.name = 'ryo'
 
'''
测试部分代码
'''
f = Foo()
print(f.name)
  • 测试日志
λ python IOC.py
call() method called!
ryo

和组合结合

组合的概念

如果要熟练应用依赖注入,我还要弄懂一个概念,那就是组合:组合的目的就是解耦,减少依赖性,原来以某个具体的值或对象传入到内部改成以参数的形式传入

在 java spring 框架中,组合是非常常见的一种方式。

一个 service 由其他的 service/mapper 组合而成。做到高内聚,低耦合。

案例

比如:在实例Bar对象时,封装Foo对象,实例Foo对象封装Head对象,就用参数的形式传入到构造方法里

'''
desc: 依赖注入组合测试案例
author: binbin.hou
'''
class Mapping:
	# 映射集合
	mapping_col = {}
	
	@staticmethod
	def register(cls,value):
		Mapping.mapping_col[cls]=value
		
	@staticmethod
	def getCls(cls):
		return Mapping.mapping_col[cls]

		
class MyType(type):

    def __call__(cls,*args,**kwargs):
        obj = cls.__new__(cls,*args,**kwargs)
        print('call() method called!')
        args_list = list(args)
        args_list.append(Mapping.getCls(cls))
        obj.__init__(*args_list,**kwargs)
        return obj
 
 
class Foo():
 
    def __init__(self):
        self.name = 'ryo'
		
    def f(self):
        print('This name: ', self.name)
 
class Bar(metaclass=MyType):
 
    def __init__(self,obj):
        self.f = obj.f
 
    def f2(self):
        self.f()
 
'''
测试部分代码
'''
# 注册
Mapping.register(Bar,Foo())
# 测试
b = Bar()
b.f2()
  • 测试日志信息
$ python IOC_combine.py
call() method called!
This name:  ryo

常见报错

问题

TabError: inconsistent use of tabs and spaces in indentation

解决方式

使用空格代替 tab 符号。

【首选项】=》【语言】=》【Python】=》【制表符设置】勾选上替换为空格。

参考资料

python中的接口和依赖注入

  • nodepad++ 的 tab 问题

https://www.cnblogs.com/cbl321/p/8074146.html