普通的例子
首先我们先看一个普通的类:
class Foo:
def __init__(self):
self.name = 'ryo'
def f1(self):
print(self.name)
基础知识
首先要明确的是,在python里,一切事物皆为对象
而所有的类都是对象,默认是由type创建
创建类的执行流程
-
遇到class关键词,执行type的
__init__
方法,创建Foo类这个对象 -
遇实例化对象(obj=Foo()),执行type里的
__call__
方法 -
在call方法里调用Foo类的
__new__
方法(负责创建对象) -
执行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】=》【制表符设置】勾选上替换为空格。
参考资料
- nodepad++ 的 tab 问题
https://www.cnblogs.com/cbl321/p/8074146.html