python闭包

https://www.cnblogs.com/lovesqcc/p/8087510.html

  1. 修改前
def commonGenerate(startTime, endTime, field, values):
    reqs = []
    for val in values:
        requestId = str(startTime) + "_" + str(endTime) + "_" + val
        baseReq = json.loads(baseExportReqStr)
        baseReq['osp']['start_time'] = startTime
        baseReq['osp']['end_time'] = endTime
        baseReq['osp'][field] = [val]
        baseReq['request_id'] = requestId
        reqs.append(json.dumps(baseReq))
    return reqs

def generateReqByState(startTime, endTime):
    states = ["S1", "S2", "S3", "S4", "S5", "S6"]
    return commonGenerate(startTime, endTime, 'state', states)

def generateReqByOrderType(startTime, endTime):
    orderTypes = ["T1", "T2", "T3"]
    return commonGenerate(startTime, endTime, 'type', orderTypes)

def generateReqByExpressType(startTime, endTime):
    expressTypes = ["E1", "E2", "E3"]
    return commonGenerate(startTime, endTime, 'expr_type', expressTypes)

def generateReqByFeedback(startTime, endTime):
    feedbacks = ["F1", "F2"]
    return commonGenerate(startTime, endTime, 'fb', feedbacks)

def getGenerateFuncs():
    gvars = globals()
    return [ gvars[var] for var in gvars if var.startswith('generateReq')  ]

caseGenerateFuncs = getGenerateFuncs()
print (caseGenerateFuncs)
  1. 修改后
def commonGenerator(startTime, endTime, field, values):
    def generateReqInner(startTime, endTime):
        reqs = []
        for val in values:
            requestId = str(startTime) + "_" + str(endTime) + "_" + val
            baseReq = json.loads(baseExportReqStr)
            baseReq['osp']['start_time'] = startTime
            baseReq['osp']['end_time'] = endTime
            baseReq['osp'][field] = [val]
            baseReq['request_id'] = requestId
            reqs.append(json.dumps(baseReq))
        return reqs
    return generateReqInner

def generateGenerators(startTime, endTime, configs):
    gvars = globals()
    for (field, values) in configs.items():
        gvars['generateReqBy' + field] = commonGenerator(startTime, endTime, field, values)

configs = {"state": ["S1", "S2", "S3", "S4", "S5", "S6"], 
           "type": ["T1", "T2", "T3"], 
           "expr_type": ["E1", "E2", "E3"], 
           "fb": ["F1", "F2"]
           }

def getGenerateFuncs():
    gvars = globals()
    return [ gvars[var] for var in gvars if var.startswith('generateReq')  ]

generateGenerators(startTime, endTime, configs)
caseGenerateFuncs = getGenerateFuncs()
print caseGenerateFuncs

'''
这里函数 commonGenerator 对 commonGenerate 做了一点改动,不再直接返回值列表,而是根据不同的参数返回一个处理不同的函数,这个函数会返回值列表; 
然后 generateGenerators 根据指定配置 configs, 调用 commonGenerator 来批量生产generateReqByXXX函数。妙不妙,生产函数的函数 !
'''
'''
按维基的解释: 闭包是引用了自由变量的函数。在例子中,闭包就是 generateReqInner , 引用了传入的自由变量 field, values, 从而在 commonGenerator 调用结束之后,generateReqInner 依然存在能够被访问,且功能效果等同于 generateReqInner(startTime, endTime, field, values) 。

知乎上有句话很有启发性: 闭包就是一种特殊性质的数据,只不过这种数据恰好是携带了数据的代码块,是一个潜伏起来的随时待执行的完整的对象体(数据-行为绑定的执行体)。从这个角度来说,也可以理解闭包的实现:

要件一: 闭包必定存在于一个封闭的作用域 D; 例子中这个 D 就是 commonGenerator 函数的作用域;
要件二: 处于封闭作用域的代码块访问了在代码块作用域之外的封闭作用域里的自由变量。
若只访问自身里的参数及局部变量,就是普通代码块;当封闭作用域结束后,里面的一切都会被销毁; 如果这个代码块,除了访问自身的参数及局部变量,还访问在它之外的封闭作用域里的变量,那么,这个普通代码块就升级为闭包,其访问的自由变量和这个代码块将会共同保存并独立于封闭作用域的存在; 当封闭作用域结束后,这个闭包不会一同消亡,而是继续独立存在。 例子中,generateReqInner 访问了其作用域之外的封闭作用域里的参数 field, values, 从而变成了独立于commonGenerator 的闭包。
'''
  1. 经典的例子【outer2()()会怎么样?outer3和outer4的坑经常遇到】
def outer():
    def inner():
        count = [1]
        print 'inner: ', count[0]
        count[0] += 1
    return inner

def outer2():
    count = [1]
    def inner2():
        print 'inner2: ', count[0]
        count[0] += 1
    return inner2

def outer3(alist):
    inners = []
    for e in alist:
        def inner3():
            print 'inner3: ', e
        inners.append(inner3)
    return inners

def outer4(alist):
    inners = []
    for e in alist:
        def inner4(g):
            def inner():
                print 'inner4: ', g
            return inner
        inners.append(inner4(e)) # 传入循环变量e
    return inners

if __name__ == '__main__':
    inner = outer()
    inner()
    inner()
    inner2 = outer2()
    inner2()
    inner2()

    for outer in [outer3, outer4]:
        inners = outer([1,2,3])
        for inner in inners:
            inner()

''' output
inner:  1
inner:  1
inner2:  1
inner2:  2
inner3:  3
inner3:  3
inner3:  3
inner4:  1
inner4:  2
inner4:  3
'''
原文地址:https://www.cnblogs.com/amize/p/14747407.html