python装饰器执行机制

前沿:

首先是看到了单例模型,想不明白 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
View Code

这样我就十分奇怪了,但后来将 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)

下面奉上原理图

 

原文地址:https://www.cnblogs.com/fuzzier/p/7543711.html