python 装饰传入一个函数,添加一些功能,然后返回它
先了解闭包的功能,对理解装饰器有很大的帮助
什么是闭包 (closure),如何捕获变量
def dog():
height = 40
def profile():
print("I'm a dog and my height is {}".format(height))
return profile
if __name__ == "__main__":
dog_profile = dog()
dog_profile()
function dog() 里面包了一个和 profile() function,在调用的 dog() 会返回 profile,在一般认知中,function 中的
variable 其 life cycle(生命周期) 会随函数执行完而消灭,理论上变量 height 在执行完 function dog() 后就要消失,但在 dog_profile()(调用 profile()) 时还能够找到 variable height,原因就是 return profile 时,函数 profile capture 住了 variable,把属于上一层的变量偷渡到自己函数范围,带有 capture variable 的函数就是闭包.
def dog():
height = 40
def grow_up():
height = height +1
return grow_up
if __name__ == "__main__":
dog_grow_up = dog()
dog_grow_up()
报错 UnboundLocalError,一般用 global 声明变量,如果在某个函数中同样命名的变量要赋值的话,一样会报 UnboundLocalError,在 python 中,对变量赋值就等于建立局部变量
global x
x = 10
def add_x():
x = x +1
if __name__ == "__main__":
add_x()
def dog():
height = 40
def grow_up():
nonlocal height
height = height +1
print("Thanks for making me growing up.I'm now {} meters!!!".format(height))
return grow_up
if __name__=="__main__":
dog_grow_up = dog()
dog_grow_up()
# defining a decorator
def hello_decorator(func):
# inner1 is a Wrapper function in
# which the argument is called
# inner function can access the outer local
# functions like in this case "func"
def inner1():
print("Hello, this is before function execution")
# calling the actual function now
# inside the wrapper function.
func()
print("This is after function execution")
return inner1
# defining a function, to be called inside wrapper
def function_to_be_used():
print("This is inside the function !!")
# passing 'function_to_be_used' inside the
# decorator to control its behavior
function_to_be_used = hello_decorator(function_to_be_used)
# calling the function
function_to_be_used()
Output:
Hello, this is before function execution This is inside the function !! This is after function execution
def print_func_name(func):
def warp_1():
print("Now use function '{}'".format(func.__name__))
func()
return warp_1
def print_time(func):
import time
def warp_2():
print("Now the Unix time is {}".format(int(time.time())))
func()
return warp_2
@print_func_name
@print_time
def dog_bark():
print("Bark !!!")
if __name__ == "__main__":
dog_bark()
# > Now use function 'warp_2'
# > Now the Unix time is 16532445
# > Bark !!!
dog_bark 会先被@print_time吃进去,然后吐出一个 warp_2 的 function,然后这个 warp_2 的 function 又会被 print_func_name 吃进去,返回一个叫做 warp_1 的 function
class myDecorator:
def __init__(self,fn):
print("inside myDecorator.__init__()")
self.fn = fn
def __call__(self):
self.fn()
print("inside myDecorator.__call__()")
@myDecorator
def aFunction():
print("inside aFunction()")
print("Finished decorating aFunction()")
# 输出
# inside myDecorator.__init__()
# Finished decorating aFunction()
# inside aFunction()
# inside myDecorator.__call__()
被 decoratoe 的函数其实已经是另一个函数了,如果你查询一下 function.__name__
的输出是” wrapper”.
这会给程序埋坑,python 的 functool 包中提供一个叫 wrap 的 decorator 来消除副作用
from functools import wraps
def hello(fn):
@wraps(fn)
def wrapper():
print("hello, %s"%fn.__name__)
fn()
print("goodby, %s"%fn.__name__)
return wrapper
@hello
def foo():
'''foo help doc'''
print("I am foo")
pass
foo()
print(foo.__name__)
print(foo.__doc__)
参考文章
https://coolshell.cn/articles/11265.html