理解装饰器
1.函数名
函数名是函数的名字,本质:变量,特殊的变量。
1)函数名存着函数的内存地址。
内存地址:
2)第一类对象(first-class object)
1.可以在运行期间创建 2.可用作函数参数或返回值 3.可存入变量的实体。
2.闭包
1、 闭包函数 : 内部函数包含对外部作用域而非全局作用域变量的引用,该内部函数称为闭包函数
2、闭包的作用:爬虫、装饰器
当程序执行遇到函数执行时,会在内存空间开辟局部命名空间,当函数执行完毕,该命名空间会被销毁。但是如果这个函数内部形成闭包,则该内存空间不会随着函数执行完而消失。
3、如何判断是否是闭包:print(函数名.__closure__) 结果是 cell 说明是闭包,结果是 None 说明不是闭包。
如何判断它是否是一个闭包函数呢? 内层函数名.__closure__ cell 就是=闭包
def wrapper(): name = 'summer' def inner(): print(name) #可以使用外部作用域,但不是全局作用域 inner() print(inner.__closure__) wrapper()
结果:
3.装饰器
3.1了解装饰器
装饰器是可调用的对象。其参数是被装饰的函数。装饰器可能会处理当前函数。然后把它(函数变量)返回,或者将其替换成另一个函数或可调用对象。
装饰器本质: 就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。
import time
def timmer(f):
def inner():
start_time = time.time()
f()
end_time = time.time()
print('此函数的执行时间为{}'.format(end_time - start_time))
return inner
def func1():
print('in func1')
time.sleep(1)
func1 = timmer(func1)
print(func1)
func1() # 这里的func1是全新的func1,就是上面的赋值,此时相当于执行 inner函数
输出结果:
<function timmer.<locals>.inner at 0x03822DF8>
in func1
此函数的执行时间为1.0003533363342285
语法糖: 想测试谁,前面加@装饰器函数,即可。 写装饰器,约定俗成,函数名为wrapper
def wrapper(func): def inner(*args,**kwargs): '''被装饰函数之前''' ret = func(*args,**kwargs) # 被装饰的函数 '''被装饰函数之后''' return ret return inner @wrapper def func(*args,**kwargs): print(args,kwargs) return 666 print(func()) 输出结果: () {} 666
装饰器利用return制造了一个假象,func()执行,其实是执行inner() , func()把原来的func()给覆盖了。
2。python何时执行装饰器
import functools def dec(func): @functools.wraps(func) # 加这句是为了防止装饰器对被装饰函数的影响 def wrapper(*args, **kwargs): print('this is a wrapper') return func(*args, **kwargs) return wrapper @dec # foo = dec(foo) def foo(): print('foo() called') foo() # dec -> foo= dec(foo) ->return wrapper-> foo = wrapper() ->print('this is a wrapper') return foo() -> print('foo() called')
首先说明@dec
的含义,这可以看作是foo=dec(foo)
的一种简写(这其实类似于数学中的函数复用),既然如此,那么在foo()
前加上@dec
相当于foo=wrapper
。剩下的就是类似例3的过程了,首先执行装饰器内的打印语句,然后返回foo()
,执行真实的foo()
内容。实际上上述过程省略了一个重要的点,那就是装饰器函数在被装饰函数定义好后立即执行,这个如何理解呢,可以理解为当被装饰函数定义好后,即执行了foo=dec(foo)
操作,因此实际上在例4中,可以将上例稍做修改,再去掉最后一行的foo()
def dec(func): print('this is dec') @functools.wraps(func) # 加这句是为了防止装饰器对被装饰函数的影响 def wrapper(*args,**kwargs): print('this is a wrapper') return func(*args,**kwargs) return wrapper @dec def foo(): print('foo() called')
详细解释:https://blog.csdn.net/shahuzi/article/details/81254557