前沿:
首先是看到了单例模型,想不明白 outer中的参数 为什么能像 global的参数 一样屹立不倒。
#单例模型 def single_model(cls): instance = {} def inner(*args, **kwargs): print if cls not in instance: instance[cls] = cls(*args, **kwargs) print 'cls not in instance' return instance[cls] return inner @single_model class MyFoo(object): def __init__(self): self.name = 'wwt' self.age = 12 mf1 = MyFoo() mf2 = MyFoo() mf1.name = 'asfaf' print mf2.name print mf1 is mf2 [out:] asfaf True
这样我就十分奇怪了,但后来将 instance 放在 inner 中单例模型就失败了,所以问题一定在装饰器的 outer 上。
1 装饰器个层级之间的执行顺序
def single_model(text): print 'last_outer ' + text def outer(func): instance = {} print 'instance_outer: %d' % id(instance) def inner(*args, **kwargs): if func not in instance: instance[func] = func(*args, **kwargs) print 'instance_inner: %d' % id(instance) return instance[func] return inner return outer @single_model('zhhh') def func(): return 'hahahha' con1 此时此刻执行程序 [out:] last_outer zhhh instance_outer: 31691640 # 也就是说装饰器创建后,他会在func调用前执行。 ----------------------------------------------- con2 调用函数 abc = func() efg = func() print abc, efg [out:] last_outer zhhh instance_outer: 30905208 instance_inner: 30905208 hahahha hahahha # 如果在outer或更outer层定义了对象(instance)并在inner层引用,则该对象不会被GC,会存在, # 类似于global
2 多个装饰器在一个函数或对象上的调用机制(一例详解)
# 记录程序执行的位置 def position(text): print "[POSITION] %s" % text def func1_outer(func): position("func1_outer") print 'func1_outer call %s' % func.__name__ def func1_inner(arg1, arg2): position("func1_inner") print "func1_inner call %s" % func.__name__ return func(arg1, arg2) return func1_inner def func2_outer(flag=False): position("func2_outer") def func2_mid(func): position("func2_mid") print "func2_mid call %s" % func.__name__ def func2_inner(arg1, arg2): position("func2_inner") if flag: print 'func2_inner result is %d' % ((arg1+arg2)*flag) return func(arg1, arg2) return func2_inner return func2_mid print 'Declaring my_func' @func1_outer @func2_outer(flag=2) def my_func(arg1, arg2): position("my_func") print 'my_func result is %d' % (arg1+arg2) return True print 'Start my_func' my_func(1, 2) [out:] Declaring my_func # 首先按照程序顺序执行第一个全局print [POSITION] func2_outer # 转到func2_outer [POSITION] func2_mid # 转到func2_mid func2_mid call my_func # 执行func2_mid的 func.__name__ [POSITION] func1_outer # 转到func1_outer func1_outer call func2_inner # 执行func1_outer的 func.__name__ Start my_func # 运行my_func(1, 2) [POSITION] func1_inner # 转到 func1_inner func1_inner call func2_inner # 执行func_inner的 func.__name__ [POSITION] func2_inner # 转到 func2_inner func2_inner result is 6 # 执行func2_inner 内的算式 [POSITION] my_func # 转到my_func my_func result is 3 # 执行my_func
my_func(1, 2)相当于
temp = funn2_outer(flag=2)(my_func)
fun1_outer(temp)
my_func(1, 2)
下面奉上原理图