1.闭包
了解装饰器前,先了解什么是闭包?
维基百科解释:
闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。 [1]
看完可能还是很模糊,所以到底什么是闭包呢?
其实闭包就是,函数a返回值返回的是一个函数b,这个函数b就是称为闭包
def a():
print("this is function a")
def b():
print("this is function b")
return b#返回函数b
#output:<function a.<locals>.b at 0x000001A44B0894C0>
# return b() #调用函数b
#output: 分二个,当直接调用variable(),#this is function a
#this is function b
#print(variable()),#this is function a
#this is function b
#None
a()#调用函数a
variable = a #这里只是将a函数指向变量variable
print(variable) #<function a at 0x000001F557029310>
print(variable()) #this is function a
#<function a.<locals>.b at 0x0000021FEE2794C0>
variable = a() #思考这里,装饰器会有用到, 函数a赋值给了变量
variable()
闭包实现数据的封装和复用,装饰器就是闭包的一种
2.装饰器
装饰器。。。具体又是如何呢?
根据上面的闭包基础在添加一个 函数作为参数传给另外的函数
def a():
print("this is function a()")
def funa(fun):
print("this is function funa(fun)")
def funb():
print("this is function funb()")
fun()
return funb()
funa(a)
this is function funa(fun)
this is function funb()
this is function a()
装饰器(decorator)也称装饰函数,不仅可以装饰函数,也可以装饰对象。其主要是用于某些函数需要拓展功能,但又不希望修改原函数,它就是语法糖,使用它可以简化代码、增强其可读性,当然装饰器不是必须要求被使用的,不使用也是可以的,Python 中装饰器通过 @ 符号来进行标识——***@装饰器函数(类)名***。
# def a():
# print("this is function a()")
def funa(fun):
print("this is function funa(fun)"+ fun.__name__ + '')
def funb():
print("this is function funb()")
fun()
return funb #这里有个说法 不能写funb()
#funa(a)
#variable = funa(a)
@funa
def b():
print("this is b()")
#b()
b = funa(b) #等于@funa 就是吧 funa函数带函数b 指向变量b
b()
this is function funa(fun)b
this is function funa(fun)funb
this is function funb()
this is function funb()
this is b()
到这里才是知道什么是装饰器,装饰器的应用很多,很多博客,但建议先菜鸟教程/w3c教程。
此文章后建议继续看看菜鸟的后半部分
https://www.runoob.com/w3cnote/python-func-decorators.html
授权(Authorization)
from functools import wraps
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
authenticate()
return f(*args, **kwargs)
return decorated
日志(Logging)
from functools import wraps
def logit(func):
@wraps(func)
def with_logging(*args, **kwargs):
print(func.__name__ + " was called")
return func(*args, **kwargs)
return with_logging
@logit
def addition_func(x):
"""Do some math."""
return x + x
result = addition_func(4)
# Output: addition_func was called
带参数的装饰器
from functools import wraps
def logit(logfile='out.log'):
def logging_decorator(func):
@wraps(func)
def wrapped_function(*args, **kwargs):
log_string = func.__name__ + " was called"
print(log_string)
# 打开logfile,并写入内容
with open(logfile, 'a') as opened_file:
# 现在将日志打到指定的logfile
opened_file.write(log_string + '\n')
return func(*args, **kwargs)
return wrapped_function
return logging_decorator
@logit()
def myfunc1():
pass
myfunc1()
基于类
class Test(object):
def __init__(self, func):
print('函数名是 %s ' % func.__name__)
self.__func = func
def __call__(self, *args, **kwargs):
self.__func()
@Test
def hello():
print('Hello ...')
hello()