python装饰器

一,python的装饰器是什么?

二,python装饰器

三,带有参数的装饰器

一,python的装饰器是什么?

python装饰器其实就是一个函数,它用于给其他函数添加一些新功能。这个就是python的装饰器。

二,python的装饰器

1,python装饰器的原则

  a,不修改被装饰的函数的原代码

  b,不修改原函数的调用方式

归纳一下其实就是装饰器对待被修饰的函数完全是透明,是感知不到装饰器的存在的。

基于以上2点给被装饰的函数添加新功能。

2,python装饰器的基本知识

a,函数即变量

b,高阶函数

c,嵌套函数

d,高阶函数+嵌套函数==》装饰器

a,函数即变量

a = 1 把内存比喻酒店的话,那么就会有间房存放1,然后存放1的房间门牌号就是a.
b = a 这个其实就是给存放1的房间多添加一个门牌号。

那么python是有垃圾回收的机制,那么怎样的情况下,才会回收1呢?
只要存放1的房间号没有门牌号,即没有函数名,那么这个1就会立马被回收。如果人为的回收,可以使用del命令即可。


那么函数和变量是一样的。比如
def test():
pass

把test作为门牌号,函数体的内容放到房间里面

当然,匿名函数也是一样的道理。如下图

 上面函数即变量的意思,其实就是你定义一个函数,其实当Python解释器执行到def 的时候并不会执行这个代码块,其实就是和存放变量一样,存放一下仅此而已。

b,高阶函数

高阶函数满足一下任一条件,即为高阶函数。

1,把一个函数名当做实参传给另外一个函数(在不修改被装饰函数的源代码的情况下为其他添加新功能)
2, 返回值中包含函数名(不修改函数的调用方式)

def a():
    print('in the a')

def b(a):
    pass

b()

  像这种就算是高阶函数的一种,符合第一个条件。

如果想要符合第二个条件,只要函数return a 就可以满足第二个条件了。

c,函数的嵌套

1,这个是函数的调用

def test1():
    print('in the test1')


def test2():
     test1()

test2()

  



2,这个是函数的嵌套

def test1():
    def test2():
    print('in the test2')
test1()

  

d,高阶函数 + 嵌套函数 = 装饰器

如下是个简单的装饰器:

import time
def timmer(func):
    def wrapper():
        start_time = time.time()
        func()
        stop_time = time.time()
        print('the func run time is {0}'.format(stop_time-start_time))
    return wrapper

def bar():
    time.sleep(2)
    
    print('in the bar')



bar = timmer(bar)

 

  可以发现,这个装饰是由高级函数和嵌套函数组成的。

这个装饰器的功能就是给函数添加运行时间的功能。其实上面的bar = timmer(bar)可以使用python提供的语法糖来写那么就更简单了。

import time
def timmer(func):
    def wrapper():
        start_time = time.time()
        func()
        stop_time = time.time()
        print('the func run time is {0}'.format(stop_time-start_time))
    return wrapper

@timmer
def bar():
    time.sleep(2)
    print('in the bar')



#bar = timmer(bar)

  

 这样一个装饰器就完成了。从这个简单的装饰器来看。我们可以发现当我们调用bar()这个函数的时候不仅仅是返回了函数的内容,而且还只能加了计算时间的功能。

仔细一看 但我们调用bar()的时候,我们可以发现其实我们调用的是wrapper这个函数,因为timmer这个函数是return wrapper这个函数地址,所以bar = wrapper ,那么咱们调用的时候

bar()其实就是等于wrapper()。

上面的简单完成了装饰器的功能,如果想把这个装饰器用于其他函数,只需在其他函数上面添加@timmer即可装饰其他函数(前提其他函数是没有参数的)

为了是上面的装饰器可以装饰其他函数,比如函数自带参数.所以咱们需要把上面的函数简单修改一下。

import time
def timmer(func):
    def wrapper(*args,**kwargs):
        start_time = time.time()
        func(*args,**kwargs)
        stop_time = time.time()
        print('the func run time is {0}'.format(stop_time-start_time))
    return wrapper

@timmer
def bar():
print('in the bar') @timmer def test(name): print ('my name is {0}'.format(name)) bar() test()

  

  为了能够是装饰器可以装饰其他函数,将传入的参数设置成冗余。所以即使test有变量,也不会影响它的装饰的功能。

上面讲到了bar = wrapper 同理 test=wrapper 所以如果test函数是需要传入参数的话,毫无疑问wrapper也是需要设置形参的。为了防止传入的参数不定,所以用*args和**kwargs来代替。当然这里传入的参数也需要使用*args和**kwargs

还有一种就是要装饰的函数是带有return值的,所以装饰器要简单改一下,即装饰器里面接受一下赋值给一个变量,然后输出。

import time
def timmer(func):
    def wrapper():
        start_time = time.time()
        result = func()
        print(result)
        stop_time = time.time()
        print('the func run time is {0}'.format(stop_time-start_time))
    return wrapper

@timmer
def bar():
    time.sleep(2)
    print('in the bar')
    return 'from bar'

bar()

  

三,带有参数的装饰器

#!/usr/bin/env python
# -*- conding:utf-8 -*-
import time
user,passwd = 'test','test123'

def auth(auth_type):
    def outer_wrapper(func):
        def wrapper(*args,**kwargs):
            username = input('username:').strip()
            password = input('password:').strip()
            if auth_type == 'local':

                if user==username and passwd==password:
                    print('登录成功!')
                    res = func(*args,**kwargs)
                    return res
                else:
                    print('登录失败')
            elif auth_type == 'ladp':
                print('ladp正在建设中!')
        return wrapper
    return outer_wrapper




def index():
    print('welcome to index page')


@auth(auth_type='local') # a= auth(参数)  home = a(home)
def home():
    print('welcome to home page')
    return 'from home'


@auth(auth_type='ladp')
def bbs():
    print('welcome to bbs page')





index()
print (home())
bbs()

  

原文地址:https://www.cnblogs.com/lin1/p/8386947.html