• 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)

    下面奉上原理图

     

  • 相关阅读:
    作业要求 20181127-2 每周例行报告
    作业要求 20181120-1 每周例行报告
    作业要求 20181113-2 每周例行报告
    作业要求 20181030-4 每周例行报告
    作业要求 20181023-3 每周例行报告
    20181016-10 每周例行报告
    20181009-9每周例行报告
    jQuery
    AJAX
    Maven和Solr简单总结
  • 原文地址:https://www.cnblogs.com/fuzzier/p/7543711.html
Copyright © 2020-2023  润新知