py学习笔记05 装饰器

递归拾遗

"""
利用函数编写如下数列:
斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,
377,610,987,1597,2584,4181,6765,10946,17711,28657,46368
前两数相加既得后一个数字
"""
def func(arg1,arg2):
    if arg1 == 0:
        print arg1, arg2
    arg3 = arg1 + arg2
    print arg3
    if arg3 > 1000:
        return arg3
    func(arg2, arg3)
func(0,1)

def func1(arg1,arg2):
    if arg1 == 0:
        pass
    arg3 = arg1 + arg2
    if arg3 > 1000:
        return arg3
    ret = func1(arg2,arg3)
    return ret
result = func1(0,1)
print result

 

装饰器

装饰器是函数,只不过该函数可以具有特殊的含义,装饰器用来装饰函数或类,使用装饰器可以在函数执行前和执行后添加相应操作。

 

学前班:

#### 第一波 ####
def foo():
    print 'foo' 
foo     #表示是函数
foo()   #表示执行foo函数
 
#### 第二波 ####
def foo():
    print 'foo'
foo = lambda x: x + 1
foo()   # 执行下面的lambda表达式,而不再是原来的foo函数,因为函数 foo 被重新定义了

 

装饰器使用场景:

假设公司有N个业务部门,1个基础平台部门,基础平台负责提供底层的功能,如:数据库操作、redis调用、监控API等功能。业务部门使用基础功能时,只需调用基础平台提供的功能即可,示例如下:

############### 基础平台提供的功能如下 ###############
 
def f1():
    print 'f1'
 
def f2():
    print 'f2'
 
def f3():
    print 'f3'
 
def f4():
    print 'f4'
 
############### 业务部门A 调用基础平台提供的功能 ###############
 
f1()
f2()
f3()
f4()
 
############### 业务部门B 调用基础平台提供的功能 ###############
 
f1()
f2()
f3()
f4()

先来查看一个最简单的装饰器代码:

#无参数的装饰器
def auth(func):   #func = f1 =====>func() <===>f1()
    def inner():
        print 'before'            #验证的内容
        func()  #f1 ====> 原函数
        print 'after'            #验证成功后执行的操作
    return inner

@auth                #等同于f1 = auth(f1)
def f1():
    print 'f1'

业务调用方法:

#装饰器执行函数
import basic
basic.f1()

执行结果为:
before
f1
after

这种装饰器的使用还是具有局限性,如果我们想要传参,应该怎么办。。。。看下面

可以传入参数的装饰器:

#有参数的装饰器
def auth_arg(func):   #func = f1 =====>func() <===>f1()
    def inner(arg):
        print 'before'
        func(arg)  #f1 ====> 原函数
        print 'after'
    return inner

#多参数的装饰器,内层函数设置成动态参数
def auth_args(func):   #func = f1 =====>func() <===>f1()
    def inner(*arg,**kwargs):
        print 'before'
        func(*arg,**kwargs)  #f1 ====> 原函数
        print 'after'
    return inner

@auth_args
def f2(arg1,arg2):
    print 'f2',arg1,arg2

@auth_args
def f5(arg):
    print 'f5',arg

此种方式业务的调用方式如下:

import basic

#有参数的装饰器
basic.f5('123')
basic.f6('1','2')

输出结果为:
before
f5 123
after

before
f6 1 2
after

可以看到已经把我们传入的参数输出了出来

装饰器小小节:

1.装饰器是一个函数
2. 执行auth_args函数,被装饰的函数作为参数auth_args(f1) auth_args 函数的返回值,
赋值给被装饰的函数的函数名

@auth_args
def f1():
    pass

3.动态参数,可以装饰含有n个参数的函数
4.函数返回值
5.多装饰器
6.至少3层,3层的如何使用?
@auth_args
    1.执行auth_args函数
    2.将auth_args函数的返回值给赋值给被装饰器的函数的函数名
@auth_args(arg)
    1.执行auth_args函数,得到返回值,result
    2.创建装饰器,@ + result结合:@result
    3...
       1).执行result 函数
       2).将result函数的返回值给被装饰器的函数的函数名

功能看似完美了,但是如果我需要返回值,怎么整。。。。。

一样可以解决,看下:

#可接收返回值得装饰器
def auth_return(func):   #func = f1 =====>func() <===>f1()
    def inner(*arg,**kwargs):
        print 'before'
        temp = func(*arg,**kwargs)  #f1 ====> 原函数
        print 'after'
        return temp
    return inner

@auth_return
def fetch_host_list(arg):
    server_list = ['c1','c2','c3']
    return server_list

业务调用如下:

import basic
#可接受返回值的装饰器
reg_list = basic.fetch_host_list('test')
print reg_list

输出结果:
before
after
['c1', 'c2', 'c3']

猪脚要来了。我们做个用户登录验证的操作吧^_^

看下面:

#用户验证装饰器
def login():
    name = 'ares'
    if name == 'ares':
        return True
    else:
        return False
def auth_login(func):   #func = f1 =====>func() <===>f1()
    def inner(*arg,**kwargs):
        if not login():
            return "非法请求"
        temp = func(*arg,**kwargs)  #f1 ====> 原函数
        print 'after'
        return temp
    return inner

@auth_login
def f7login(arg):
    server_list = ['c1','c2','c3']
    return server_list

业务调用方法:

import basic
#判断用户登录装饰器
ser_list = basic.f7login('test')
print ser_list

输出结果:
after
['c1', 'c2', 'c3']

#若login函数里传入用户名不为ares,则在此处会输出‘非法请求’

功能看似强大,但是不是很灵活,不如加个key值判断方便:

#使用key验证
def login1(key):
    local = "1231"
    if local == key:
        return True
    else:
        return False
def auth_login1(func):   #func = f1 =====>func() <===>f1()
    def inner(*arg,**kwargs):
        key = kwargs['token']
        del kwargs["token"]
        #key = kwargs.pop('token')    #这一句等于 上面注释的两句 #这句含义:因为下面的login 只接受一个参数,这里多一个参数,所有删除
        is_login = login1(key)
        if not is_login:
            return "非法用户"
        temp = func(*arg,**kwargs)  #f1 ====> 原函数
        print 'after'
        return temp
    return inner

@auth_login1
def f8login(arg):
    server_list = ['c1','c2','c3']
    return server_list

业务调用方式:

import basic
#使用key验证
key = "123"    #与函数的key不一致
ser_list1 = basic.f8login('test',token=key)
print ser_list1

key = "1231"    #与函数的key一致
ser_list1 = basic.f8login('test',token=key)
print ser_list1

输出结果分别为:

非法用户    #key不一致的情况

after        #key一致的情况
['c1', 'c2', 'c3']

 

什么,单装饰器还不牛,别急,还有多装饰器!!!

双装饰器示例:

@auth_login
@auth_login
def f1():
    pass
    
执行的结果:
就是一层套一层

双装饰用途:

双层装饰器,可以用在以下途径:
比如用户权限管理,第一层装饰器用于用户名密码验证,
第二层用在 判断用户是什么身份的用户,比如:普通用户,超级用户等

 

还有一个更屌的装饰器:

#!/usr/bin/env python
#coding:utf-8
  
def Before(request,kargs):
    print 'before'
      
def After(request,kargs):
    print 'after'
  
  
def Filter(before_func,after_func):
    def outer(main_func):
        def wrapper(request,kargs):
              
            before_result = before_func(request,kargs)
            if(before_result != None):
                return before_result;
              
            main_result = main_func(request,kargs)
            if(main_result != None):
                return main_result;
              
            after_result = after_func(request,kargs)
            if(after_result != None):
                return after_result;
              
        return wrapper
    return outer
      
@Filter(Before, After)
def Index(request,kargs):
    print 'index'
posted @ 2015-11-24 21:50  我是一条最咸的咸鱼  阅读(132)  评论(0)    收藏  举报
返回顶部