学习一下Python 装饰器用法及理解(小学生水平)

Python中的装饰器是一个特殊的函数,用于不改变原函数定义的情况下为原函数增加额外功能.

尝试理解:

如果原函数是手机屏,装饰器可以被看作是贴的膜.

  1. 贴什么膜,贴多少膜不会影响原屏幕显示的内容,也不会影响手机的运行
  2. 手机屏上有些东西是不希望因为贴膜被覆盖(比如摄像头,听筒)或改变(LOGO),所以膜会用挖孔或复制的方式处理.
  3. 如果你有多种需求时,你可以贴多张膜,也可以贴一张复合膜(钢化防窥膜)
  4. 膜可以买回来不贴,但只能贴在可贴的地方
  5. 膜和被贴对象是连在一起的,如果贴多张膜,最先贴的最靠近屏,最后贴的最先被看到.

基本用法:

最简单的用法

def decorator1(func): 	#定义装饰器.
	Return func 	#装饰器返回一个函数

@decorator1		#使用装饰器
def function1():	#原始函数

多次装饰用法

def decorator1(): 	#定义装饰器.
	Return func 	#装饰器返回一个函数
def decorator2(): 	#定义装饰器.
	Return func 	#装饰器返回一个函数

@decorator1		#再把下面生成的函数装进装饰器
@decorator2		#原函数装进装饰器,生成同名函数
Def function1():	#原始函数

复合装饰用法

def decorator 1(text):
	def decorator2(func):
		def wrapper(*args, **kw):
			print('%s %s():' % (text, func.__name__))
			return func(*args, **kw)
		return wrapper
	return decorator

@decorator1(‘xxx’)		#注意这里,相当于newDecorator= decorator1(‘xxx’) @newDecorator
 def function1():	#原始函数

实例详解

小学水平-低年级

def decorator (func):
    print('装饰器开始执行')
    return func
@decorator 
def fn1(x,y):
    print('原函数开始执行')
    return x*y
print('定义完了,准备执行')
print('fn1的执行结果为:',fn1(3,4))
----------------以下执行结果---------------
装饰器开始执行
定义完了,准备执行
原函数开始执行
fn1的执行结果为:12

可以很明显的看出@decorator时,相当于执行了fn1=decorator(fn1)准确的说是

tmp = decorator(fn1)
fn1 = tmp

小学水平-中年级

def decorator1 (func):
    print('第一个装饰器开始执行')
    return func
def decorator2 (func):
    print('第二个装饰器开始执行')
    return func
@decorator1
@decorator2
def fn1(x,y):
    print('原函数开始执行')
    return x*y
print('定义完了,准备执行')
print('fn1的执行结果为:',fn1(3,4))
----------------以下执行结果---------------
第二个装饰器开始执行
第一个装饰器开始执行
定义完了,准备执行
原函数开始执行
fn1的执行结果为: 12

可以看出,最靠近原函数的最先执行,这和贴膜一样啊:
@decorator2时,相当于执行了fn1=decorator2(fn1)
@decorator1时,相当于执行了fn1=decorator1(@decorator2)即:

fn1=decorator1(decorator2(fn1)))

但是,为啥decorator2中的print语句先执行了,而不是先遇到的decorator1中先执行呢?如何理解理顺这种执行顺序呢?
前面说了,装饰器执行时,会将跟在后面的函数送到装饰器里,生成一个新函数,并赋值给原函数名这个变量.所以要把 修饰语句和函数定义做为一个整体来看:
就像贴膜后的手机,你看到的是最外的膜,但执行贴膜动作时是从最里面的膜开始贴
所以@decorator1时,会要求@decorator2,即原函数被decorator2处理后的结果

小学水平-高年级

前面的装饰器,都是仅将原函数作为参数输入,然后输出装饰后的函数.
现在的情况是想把几个装饰器整合起来,通过参数来控制装饰结果,那要怎么做呢?
即要实现以下形式:

def  decorator(avg):
    ....
@decorator(avg)
def func(x,y):
    ....

很容易看出,要让程序可以正常执行,我们不但要让decorator返回的不但是一个函数,还得是个装饰器函数,重要的是这个返回的函数是要和原函数一样可以接收两个参数的.
试着把前面中年级的题目改写一下:

def decorator1 (avg):
    print('第一个装饰器开始执行,','输入参数为:',avg)
    def decorator2 (func):
        print('第二个装饰器开始执行')
        def func3(*args,**kw):			#这段的作用就在于让第二个装饰器来接收原函数的参数
            print('func3开始执行了')
            return func(*args,**kw)
        return func3
    return decorator2

@decorator1('hello')
def fn1(x,y):
    print('原函数开始执行')
    return x*y
print('定义完了,准备执行')
print('fn1的执行结果为:',fn1(3,4))

----------------以下执行结果---------------

第一个装饰器开始执行, 输入参数为: hello
第二个装饰器开始执行
定义完了,准备执行
func3开始执行了
原函数开始执行
fn1的执行结果为: 12

再来个例子,为函数增加写日志的装饰器,并对不同函数标注不同级别

def logging(level):
    def wrapper(func):
        def inner_wrapper(*args, **kwargs):
            print ("[{level}]: enter function {func}()".format(level=level,func=func.__name__))
            return func(*args, **kwargs)
        return inner_wrapper
    return wrapper
@logging(level='INFO')
def say(something):
    print ("say {}!".format(something))
say('哈罗')
print(say.__name__)
----------------以下执行结果---------------
[INFO]: enter function say()  注意此处INFO即装饰器参数
say 哈罗!
inner_wrapper

这就是一个复合膜的例子,不过做这个膜的厂家偷懒了,居然把手机LOGO给贴住了.
我们看到封装后的函数名被改了,所以用内置的functools.wraps 装饰器处理一下

import functools     #引入functools     
def logging(level):
    def wrapper(func):
        @functools.wraps(func)  #在这儿,把匹配原函数的新函数名改成原函数
        def inner_wrapper(*args, **kwargs):
      ...
----------------以下执行结果---------------
[INFO]: enter function say()
say 哈罗!
say  <== 函数名回来了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值