1.装饰器是一个用于封装函数或类的代码的工具。它显式的将封装器应用到函数或类上,从而使它们选择加入到装饰器的功能中【装饰器不仅可以装饰函数,也可以装饰类】。
2.对于①在函数运行前处理常见前置条件(例如确认授权),或②在函数运行后确保清理(例如输出清除或异常处理)装饰器都非常有用
a.①
def decorator_func():
// do something
decorated_func()
b.②
def decorator_func():
decorated_func()
// do something
3.对于处理已经被装饰的函数或类本身,装饰器也很有用。例如,装饰器可以将函数注册到信号系统?,或者注册到Web应用程序的URI注册表中。
4.究其核心而言,装饰器就是一个可以接受调用也可以返回调用的调用。装饰器无非就是一个函数(或调用,如有_call_method_方法的对象),该函数接受被装饰的函数作为其位置参数。装饰器通过使用该参数来执行某些操作,然后返回原始参数或一些其他的调用(大概以这种方式与编译器交互)
5.由于函数在python中是一级对象?,因此它们能够像其他对象一样被传递到另一个函数。装饰器就是接受另一个函数作为参数,并用其完成一些操作的函数。
6.@decorator_func是在Python 2.5引入的
7.对某个可调用函数,可以使用多个装饰器。如果通过@语法使用多个装饰器,就可以按照自底向上的顺序来应用它们。
首先发生的是解释器创建add函数,然后应用decorated_by装饰器。该装饰器返回了一个可调用函数,该函数被发送给also_decorated_by装饰器,also_decorated_by也做了同样的事情,接下来结果被赋给add函数。
@also_decorated_by
@decorated_by
def add(x, y):
return x + y
8.如果要使一个类上的方法不需要这个类的实例,可以使用@classmethod或@staticmethod。
9.mock模块允许使用@mock.patch或@mock.patch.object作为装饰器。
10.Celery(常见的Python任务运行工具)使用复杂的@task装饰器来标识函数是否为异步任务。
11.编写装饰器的时机
a.附加功能
b.数据的清理或添加
c.函数注册
12.装饰器通常接受被装饰的可调用函数作为唯一参数,并且返回一个可调用函数
13.示例
a.函数注册表
b.执行时封装代码
i.functools.wraps
14.常见装饰器写法
def outer(func):
def inner():
print('do something here')
func()
return inner
def my_func():
print('this is my_func')
my_func = outer(my_func)
my_func()
'''
do something here
this is my_func
'''
15.装饰器的作用:在不改变已有函数的源代码的情况下,给函数增加新的功能
16.装饰器的功能特点
a.不修改已有函数的源代码
b.给已有函数增加额外的功能
17.装饰器符合了开发中的封闭开放原则
18.装饰器的本质是闭包
19.装饰器就是把一个函数当做参数传递给闭包中的外部函数,同时在内部函数中使用这个函数,并给它添加新的功能
20.装饰带有参数的函数:让inner函数的参数和被装饰函数的参数保持一致
def logging(fn):
def inner(a, b):
res = fn(a, b)
print(res)
return inner
@logging
def sum_num(a, b):
res = a + b
return res
sum_num(1, 2)
'''
3
'''
21.装饰带有返回值的函数:在inner函数中返回被装饰函数的返回值即可
def logging(fn):
def inner(a, b):
res = fn(a, b)
return res
return inner
@logging
def sum_num(a, b):
res = a + b
return res
print(sum_num(1, 2))
'''
3
'''
- 装饰带有不定长参数的函数
def logging(fn):
def inner(*args, **kwargs):
fn(*args, **kwargs)
return inner
@logging
def sum_num(*args, **kwargs):
print(args, kwargs)
sum_num(1, 2, 3, age=18)
'''
(1, 2, 3) {'age': 18}
'''
23.通用装饰器
def logging(fn):
def inner(*args, **kwargs):
return fn(*args, **kwargs)
return inner
@logging
def sum_num(*args, **kwargs):
print(args, kwargs)
sum_num(1, 2, 3, age=18)
'''
(1, 2, 3) {'age': 18}
'''
- 带有参数的装饰器
a.装饰器的外部函数只能接受被装饰的函数这一个参数
b.如果需要给装饰器传参数需要在装饰器外部再增加一个函数
def logging(flag):
def decorator(fn):
def inner(num1, num2):
print(flag, fn(num1, num2))
return inner
return decorator
@logging('abc')
def add(a, b):
return a + b
add(1, 2)
'''
abc 3
'''
25.__call__方法的使用
a.如果一个类实现了__call__方法,那么这个类创建的对象就是一个可调用对象,可以像函数一样进行调用
class Check(object):
def __call__(self, *args, **kwargs):
print('this is __call__ function')
c = Check()
c()
'''
this is __call__ function
'''
26.类装饰器
class Check(object):
def __init__(self, fn):
self.__fn = fn
def __call__(self, *args, **kwargs):
print('验证')
self.__fn()
@Check
def comment():
print('发表评论')
comment()
'''
验证
发表评论
'''
标签:__,函数,fn,python,inner,长文,千字,装饰,def
From: https://blog.csdn.net/qq_32862515/article/details/140569520