Python之函数的本质、闭包、装饰器
函数名的本质
函数名本质上就是函数的内存地址。
1.可以赋值给其他变量,被引用
def func(): print('in func') f = func print(f)
2.可以被当作容器类型的元素
def f1(): print('f1') def f2(): print('f2') def f3(): print('f3') l = [f1,f2,f3] d = {'f1':f1,'f2':f2,'f3':f3} #调用 l[0]() d['f2']()
3.可以当作函数的参数和返回值
def f1(): print('f1') def func1(argv): argv() return argv f = func1(f1) f()
第一类对象(first-class object)指 1.可在运行期创建 2.可用作函数参数或返回值 3.可存入变量的实体。 #可以当做普通变量用!
闭包
闭包函数:
内部函数包含对外部作用域而非全剧作用域变量的引用,该内部函数称为闭包函数
#函数内部定义的函数称为内部函数
def wrapper(): name='laozhang' def inner(): print(name) inner() print(inner.__closure__) #检测是不是闭包 cell 就是b包 wrapper()
'''
输出内容:
laozhang
(<cell at 0x0000000002167498: str object at 0x00000000026D6CB0>,)
'''
由于有了作用域的关系,我们就不能拿到函数内部的变量和函数了。如果我们就是想拿怎么办呢?返回呀!
我们都知道函数内的变量我们要想在函数外部用,可以直接返回这个变量,那么如果我们想在函数外部调用函数内部的函数呢?
是不是直接就把这个函数的名字返回就好了?
这才是闭包函数最常用的用法
判断闭包函数的方法__closure__
#输出的__closure__有cell元素 :是闭包函数 def func(): name = 'eva' def inner(): print(name) print(inner.__closure__) return inner f = func() f() #输出的__closure__为None :不是闭包函数 name = 'egon' def func2(): def inner(): print(name) print(inner.__closure__) return inner f2 = func2() f2()
闭包嵌套
def wrapper(): money = 1000 def func(): name = 'eva' def inner(): print(name,money) return inner return func f = wrapper() i = f() i()
'''
eva 1000
'''
闭包的用处:
如果说内存函数是个闭包,python内部有一个机制,遇到闭包,会在内存中开启一个内存空间(不会关闭),不会随着函数的结束而关闭,能够节省创建新内存的时间和使用频率。
应用:网页爬虫
from urllib.request import urlopen def index(): url = "http://www.xiaohua100.cn/index.html" def get(): return urlopen(url).read() return get xiaohua = index() content = xiaohua() print(content)
装饰器
在不改变原函数的基础上,增加其他功能。(验证登录、测试时间、打印日志)
1.简单的装饰器
import time def func(): print('更健康') def timmer(f): def inner(): start_time = time.clock() time.sleep(0.1) f() end_time = time.clock() print('执行时间为%s'%(end_time - start_time)) return inner func = timmer(func) func()
'''
更健康
执行时间为0.0998653700182556
'''
2.语法糖(简单版本的装饰器):
将@装饰器的函数名,放在被装饰的函数之前。
import time def timmer(f): def inner(): start_time = time.clock() time.sleep(0.1) f() end_time = time.clock() print('执行时间为%s'%(end_time - start_time)) return inner @timmer #相当于func = timmer(func) def func(): print('更健康') func() #inner()
'''
更健康
执行时间为0.1004682374539092
'''
3.带参数的装饰器
import time def timmer(f): def inner(*args,**kwargs): start_time = time.clock() time.sleep(0.1) f(*args,**kwargs) end_time = time.clock() print('执行时间为%s'%(end_time - start_time)) return inner @timmer #相当于func = timmer(func) def func(a): print('%s更健康'%a) @timmer #相当于func1 = timmer(func1) def func1(a,b): print('%s和%s更健康'%(a,b)) func('老哥') # func1('老哥','杀毒软件')
'''
老哥更健康
执行时间为0.10024377977801449
老哥和杀毒软件更健康
执行时间为0.09983056346016456
'''
4.带返回值的装饰器
import time def timmer(f): def inner(*args,**kwargs): start_time = time.clock() time.sleep(0.1) ret = f(*args,**kwargs) #222 end_time = time.clock() print('执行时间为%s'%(end_time - start_time)) return ret return inner @timmer #相当于func = timmer(func) def func(a): #a:老哥 return 222 print(func('老哥'))
'''
执行时间为0.0996239553012396
222
'''
5.通用装饰器
def wrapper(func): def inner(*args,**kwargs): '''执行函数前的操作''' ret = func(*args,**kwargs) '''执行函数后的操作''' return ret return inner @wrapper def func(): print(66)
func()