Python从进阶到高级—通俗易懂版(四)
# ==================================
# Author : Mikigo
# Env :deepin 20.4 os
# ==================================
1、装饰器
装饰器就是使用 @ 符号,像帽子一样扣在函数的头上,是 Python 中的一种语法糖。
前面讲类方法和静态方法的时候提到过,使用方法非常简单。
原理实际上就是将它所装饰的函数作为参数,最后返回这个函数。
@classmethod
def mikigo():
print("My name is mikigo")
这样的写法等同于
def mikigo():
print("My name is mikigo")
mikigo = classmethod(mikigo)
对比一下,使用装饰器可读性很高,很优雅是吧,语法糖就是给你点糖吃,让你上瘾。
定义一个装饰器
- 不带参数的装饰器
举个例子:
def logger(func):
def wrapper(*args, **kw):
print('我要开始搞 {} 函数了'.format(func.__name__))
func(*args, **kw) # 函数执行
print('搞完了')
return wrapper
这是一个简单的装饰函数,用途就是在函数执行前后分别打印点日志。
有2点需要注意:
(1)装机器是一种高阶函数,在函数内层定义函数,并返回内层函数对象,多层级同理。
(2)最外层函数传入的参数是被装饰函数的函数对象。
@logger
def add(x, y):
print('{} + {} = {}'.format(x, y, x+y))
来,试试看
add(5, 10)
我要开始搞 add 函数了
5 + 10 = 15
搞完了
- 带参数的装饰器
from functools import wraps
def logger(say_some):
@wraps
def wrapper(func):
def deco(*args, **kw):
print("搞之前我先说两句:{}".format(say_some))
print('我要开始搞 {} 函数了:'.format(func.__name__))
func(*args, **kw) # 函数执行
print('搞完了')
return deco
return wrapper
你看,都是外层函数返回内层函数对象,参数放在最外层。@wraps
可加可不加,它的用途主要是保留被装饰函数的一些属性值。
@logger("别整,不得劲儿~")
def add(x, y):
print('{} + {} = {}'.format(x, y, x+y))
执行试试
add(5, 10)
搞之前我先说两句:别整,不得劲儿~
我要开始搞 add 函数了:
5 + 10 = 15
搞完了
很奈斯,就这点儿东西。
这是最常见的实现方法,现在咱们搞点不一样的。
基于类实现装饰器
基于类装饰器的实现,必须实现 __call__
和 __init__
两个魔法函数。
- 不带参数的类装饰器
class logger:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print('我要开始搞 {} 函数了'.format(self.func.__name__))
f = self.func(*args, **kwargs)
print('搞完了')
return f
不带参数的类装饰,func 是通过 init 函数里面构造的。
试试看
@logger
def add(x, y):
print('{} + {} = {}'.format(x, y, x+y))
add(5, 10)
我要开始搞 add 函数了
5 + 10 = 15
搞完了
so easy 哈,鸭子类型,实现了装饰器协议,就是装饰器对象。
- 带参数的类装饰器
class logger:
def __init__(self, say_some):
self.say_some = say_some
def __call__(self, func):
def wrapper(*args, **kwargs):
print("搞之前我先说两句:{}".format(self.say_some))
print('我要开始搞 {} 函数了'.format(func.__name__))
func(*args, **kwargs)
print('搞完了')
return wrapper
带参数的类装饰器,func 是在 call 函数里面,参数是通过 init函数传入的,这里区别比较大哈。
@logger("别整,真的不得劲儿~")
def add(x, y):
print('{} + {} = {}'.format(x, y, x+y))
add(5, 10)
搞之前我先说两句:别整,真的不得劲儿~
我要开始搞 add 函数了
5 + 10 = 15
搞完了
这类属于装饰器的高阶用法了,在一些优秀的框架源码里面比较常见。
本文来自博客园,作者:mikigo,转载请注明原文链接:https://www.cnblogs.com/mikigo/p/16812956.html