python基础____学习笔记12 (装饰器)

一、装饰器

装饰器本身是个闭包函数,即函数参数是个函数,在函数里面定义了一个函数,并且返回值是个内部函数。
装饰器的特点:
       不修改已有函数的源代码;也不修改已有函数的调用方式;给已有函数添加额外的功能

 1.1 装饰器的原理

     def decorator(fn): # fn:目标函数.
         def inner():
             '''执行函数之前'''
             fn() # 执行被装饰的函数
             '''执行函数之后'''
         return inner

示例:

def myDecorator(func):

    def innerFunc(name,age):
        print('装饰器只执行中')
        func(name,age)
        print('装饰器只执行结束')

    return innerFunc

def myfunc(name,age):
    print(f'my name is {name} ,{age} years old!')

mydec = myDecorator(myfunc)
mydec('xiaoming',22)

#装饰器只执行中
#my name is xiaoming ,22 years old!
#装饰器只执行结束

装饰器函数参数为 被装饰的函数,返回值是内部函数,因此执行这个装饰器函数 首先以被装饰函数为实参传给装饰器函数,然后返回值复制给一个变量,这个变量就是装饰器内部函数的别名,然后用被装饰函数的实参传入这个函数 进行调用

1.2 装饰器语言糖写法
只需要在被装饰的函数上面加上 @装饰器函数名。 因此如果希望多个函数被装饰,只需要再函数上面加上 @装饰器函数名

那么调用被删除函数时,就会自动调用装饰函数的内部函数.

def myDecorator(func):

    def innerFunc(name,age):
        print('装饰器只执行中')
        func(name,age)
        print('装饰器只执行结束')

    return innerFunc


@myDecorator
def myfunc(name,age):
    print(f'my name is {name} ,{age} years old!')

myfunc('xiaoming',22)
print(myfunc.__name__)  # 输出innerFunc

发现一个有趣的现象,myfunc 的名字 却变成了innerFunc了. 需要把原始函数的__name__等属性复制到innerFunc()函数中,否则,有些依赖函数签名的代码执行就会出错。
使用functools.wraps 完成此功能

import functools
def myDecorator(func):
    @functools.wraps(func)
    def innerFunc(name,age):
        print('装饰器只执行中')
        func(name,age)
        print('装饰器只执行结束')
    return innerFunc

@myDecorator
def myfunc(name,age):
    print(f'my name is {name} ,{age} years old!')

myfunc('xiaoming',22)
print(myfunc.__name__) #输出myfunc

 

1.3  不定长参数 装饰器的语法格式:

# 通用装饰器
def decorator(fn):
  def inner(*args, **kwargs):
      print('装饰器只执行中')
      result = fn(*args, **kwargs)
	  print('装饰器只执行结束')
      return result
	  
  return inner
  
def func(arg1, arg2,arg3)
	return 'xxxxx'

#调用
func(参数1,参数2,arg3=参数3) #args 收集 参数1,参数2,   kwargs 收集参数3

示例:

def myDecorator(func):

    def innerFunc(*args,**kwargs):
        print('装饰器只执行中')
        func(*args,**kwargs)
        print('装饰器只执行结束')
    return innerFunc

@myDecorator
def myfunc(name,age,faverate):
    print(f'my name is {name} ,{age} years old, my faverate is {faverate}')

myfunc('xiaoming',22,faverate='shuxu')


#装饰器只执行中
#my name is xiaoming ,22 years old, my faverate is shuxu
#装饰器只执行结束

1.4 带多个装饰器的使用
多个装饰器的装饰过程是: 离函数最近的装饰器先装饰,然后外面的装饰器再进行装饰,由内到外的装饰过程

def make_div(func):
    def inner(*args, **kwargs):
        return "<div>" + func() + "</div>"
    return inner


def make_p(func):
    def inner(*args, **kwargs):
        return "<p>" + func() + "</p>"
    return inner


# 装饰过程: 1 content = make_p(content) 2 content = make_div(content)
# content = make_div(make_p(content))
@make_div
@make_p
def content():
    return "快乐家族"

result = content()

print(result)

因此先使用make_p对content函数装饰,然后使用make_div对content装饰

1.5 装饰器带参数
带参数的装饰器就是使用装饰器装饰函数的时候可以传入指定参数,语法格式: @装饰器(参数,...)
实现方式: 在装饰器外面再包裹上一个函数,让最外面的函数接收参数,返回的是装饰器,因为@符号后面必须是装饰器实例。

# 相加
flaglist = []
def make_addOrmux(flag):
    def decorator(fn):
        flaglist.append(flag)
        print('make_addOrmux--'+"decorator")
        def inner(a, b):
            if (flag == '+'):
                print("做加法")
            elif (flag == '*'):
                print("做乘法")
            return fn(a, b)

        return inner

    return decorator


@make_addOrmux("+")
def make_add(a, b):
    return a + b


@make_addOrmux("*")
def make_mux(a, b):
    return a * b


for flag in flaglist:
    print(flag)


print(make_add(2, 3))
print(make_mux(2, 3))

#输出
make_addOrmux--decorator
make_addOrmux--decorator
+
*
做加法
5
做乘法
6

在装饰器的外层定义函数make_addOrmux() ,由这个函数接受参数装饰器的参数,并返回内部装饰器
可以看出 带参数的外部装饰器 内部函数decorator 先运行,打印"make_addOrmux--decorator", 并将参数flag假如flaglist中,

也就是说 装饰器带参数这种方式,即使没有运行函数,也会直接先运行内部函数decorator 最外部的外层装饰器, 被装饰的函数被调用时,内部装饰器函数inner才会执行,这个与不带参数的装饰器的区别

1.6 类装饰器的使用
类装饰器就是用一个类来装饰 一个函数,那么首先要让类编程一个可调用的对象callable, 就也是要实现类的__call__ 函数,函数在__call_里面调用

class decoratorClass(object):
    def __init__(self, fn):
        self.__fn = fn
    def __call__(self, *args, **kwargs):
        # 添加装饰功能
        print("装饰功能开始")
        self.__fn(*args, **kwargs)
        print("装饰功能结束")


@decoratorClass
def comment(a,b):
    print('a+b={}'.format(a+b))


comment(4,5)


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值