python基础-闭包、装饰器
2018-02-27 15:51
357 查看
一、闭包(在闭包中调用需要装饰的函数,就成了装饰器)
(一)闭包的概念
内层函数总是返回外层函数的引用。内层函数以及引用的环境变量的整体称作闭包
在函数内部定义一个函数,并且这个函数用到了外部函数的变量,那么这个函数,以及用到的一些变量称之为闭包。
(二)闭包的实例
# 外部函数中的a和b称之为环境变量或者自由变量 def line_conf(a, b): def line(x): return a * x + b return line line1 = line_conf(1, 1) line2 = line_conf(10, 1) print(line1(10)) print(line2(10))
(三)在闭包修改环境变量
在python3中实现修改环境变量。def line_conf(a): # a和b都可以修改 b = 1 def line(x): # 在闭包中,修改外部函数的变量或者参数,应该用nonlocal(基本用法和global一样) nonlocal a, b b = 10 a = 10 return a * x + b return line line1 = line_conf(1) line2 = line_conf(10) print(line1(10)) print(line2(10))
在闭包中查看环境变量。
闭包使用的环境变量存储在闭包函数的属性 — 元组对象closure属性中 比如需要访问第0个环境变量的值时 closure[0].cell_contents。
def line_conf(a): b = 1000 def line(x): return a * x + b return line line1 = line_conf(1) line2 = line_conf(10) # 查看环境变量地址,是由元组组成。必须调用闭包引用才能查看 print(line1.__closure__) # 如果想取环境变量b的值,应该用__closure__[0].cell_contents print(line1.__closure__[1].cell_contents)
在python2中修改环境变量的值。
python2的出发点就是 元组不可变 但是 元组中成员的引用可以变。所以将环境变量数据打包到一个列表,这个列表在元组是可以变的。
二、装饰器 (添加额外功能,不改变原有函数代码)
(一)装饰器的功能
1、引入日志2、函数执行的时间统计
3、执行函数预备处理
4、执行函数后清理功能
5、权限校验等场景
6、缓存
(二)多重装饰器
def makebold(func): def wrapped(): return "<b>" + func() + "</b>" return wrapped def makeitalic(func): def wrapped(): return "<i>" + func() + "</i>" return wrapped # 当执行到第一个魔法糖的时候,第一个魔法堂装饰的是 text = makebold(wrapped) 这个wrapped是makeitalic的 @makebold # 当执行到第二个魔法糖的时候,第二个魔法糖装饰的是 wrapped = makeitalic(text) @makeitalic def text(): return "hello world" # <b><i>hello world</i></b> 执行顺序是从上往下,但是运行结果的效果是从下往上,穿衣服的过程!!! print(text())
(三)通用装饰器(无参,被装饰函数带参数,被装饰函数有返回值,装饰器工厂)
import time # 装饰器工厂,我们可以通过装饰器的参数,实现不同的功能,这样需要对装饰器传递参数 def gettime(arg=None): def wrapped(func): # 不定长参数,因为在装饰很多函数时,不知道到底有多少参数 def inner(*args, **kwargs): start = time.time() # 有些函数会有返回值,有些没有,那么我们在这也给一个返回值取接收。 ret = func(*args, **kwargs) end = time.retime() tm = end - start if arg: print(tm) else: print(int(tm)) return ret return inner return wrapped @gettime() def run(a): for i in range(a): pass run(10000000)
(四)类装饰器
装饰器函数其实是这样一个接口约束,它必须接受一个callable对象作为参数,然后返回一个callable对象。在Python中一般callable对象都是函数,但也有例外。只要某个对象重写了 call() 方法,那么这个对象就是callable的。class Func(object): # 首先我们要初始化函数,来作为类对象的参数 def __init__(self, func): self.func = func # 我们在实力对象的时候必须可调用,需要用call方法实现调用函数 def __call__(self, *args, **kwargs): c3ea return self.func() @Func def func1(): return "用类装饰器来装饰我" print(func1())
三、装饰器路由(在Flask中使用)
route_list = [ # ("/gettime.py", gettime), # ("/aaa.py", aaa) ] # 如果要想加额外的功能去添加路径和函数到到rout_list中 def route(url): def func1(func): # 注意在这添加的是一个元组 # 在这里我们修改了列表(全局变量),所以用global(实际上可以不用global),列表是可变数据类型。 # 问题是如果只用装饰器,那么url没有办法提供,那么我们该添加装饰器的功能,用装饰器工厂 route_list.append((url, func)) def func2(*args, **kwargs): return func(*args, **kwargs) return func2 return func1 @route("/gettime.py") def gettime(): return time.ctime().encode()
四、装饰器-functools
from functools import wraps def makebold(func): @wraps(func) # 这样的话,被装饰的func的函数名位原名,而不是wrapped() def wrapped(): return "<b>" + func() + "</b>" return wrapped
五、斐波那契实现
# -*- coding: utf-8 -*- def fbnq(n): assert(n >= 0), u'n必须大于等于0' return n if n in (0, 1) else fbnq(n - 1) + fbnq(n - 2) if __name__ == '__main__': from timeit import Timer t = Timer('fbnq(8)', 'from __main__ import fbnq') print(t.timeit()) # 12.6881980896
使用memoization方法看看能否改善。
known = {0:0, 1:1} def fbnq2(n): assert (n >= 0), 'n must be >= 0' if n in known: return known res = fbnq2(n - 1) + fbnq2(n - 2) known = res return res if __name__ == '__main__': from timeit import Timer t = Timer('fbnq2(100)', 'from __main__ import fbnq2') print(t.timeit()) # 0.228129148483
实际我们可以把memoization方法写作一个装饰器,可以应用于很多地方。
from functools import wraps def memoization(func): known = dict() @wraps(func) def wrapper(*args): if args not in known: known[args] = func(*args) return known[args] return wrapper @memoization # 装饰器 def fbnq(n): assert(n >= 0), u'n必须大于等于0' return n if n in (0, 1) else fbnq(n - 1) + fbnq(n - 2) if __name__ == '__main__': from timeit import Timer t = Timer('fbnq(8)', 'from __main__ import fbnq') print(t.timeit())
相关文章推荐
- python基础-闭包、装饰器
- python基础 lambda 冒泡 闭包和装饰
- python基础7之闭包与装饰器
- Python的高级特性7:闭包和装饰器
- Python 中的闭包与装饰器
- Python 装饰器基础
- python闭包与装饰器
- python 高阶函数 map reduce filter sorted 闭包 装饰器
- python——高阶函数——闭包 装饰
- python的闭包及装饰器 推荐
- python学习系列之python装饰器基础(6)---装饰器加参数
- python 闭包 装饰器 冒泡排序
- python 闭包和装饰器详解
- python基础系列(六)之装饰器
- Python开发基础-Day7-闭包函数和装饰器基础
- Python 闭包与装饰器
- Python闭包及装饰器
- Day4 - Python基础4 迭代器、装饰器、软件开发规范
- python正则表达式&&装饰器基础
- python基础之装饰器(实例)