• 函数装饰器


    一 什么是装饰器

    装饰器补充:http://www.cnblogs.com/luchuangao/p/6842293.html

    器即函数

    装饰即修饰,意指为其他函数添加新功能

    装饰器定义:本质就是函数,功能是为其他函数添加新功能 #装饰器本身就是函数,被装饰的也是函数。

    为什么要用装饰器:
    及开放封闭原则。
    代码上线后,就是为了尽量避免修改,不修改原函数的源代码和调用方式,并添加新的功能。 # 函数及定义和使用。

    装饰器语法:

    在被装饰上的正上方写一个@,它会把@这一行下面这一行的函数传递到函数里,再重新赋值给index。

    func就是index函数,print(func)返回得是index内存地址。

    无参装饰器:

    (1):

    输出:
    welcome to oldboy
    run time is 3.000171661376953

    执行过程:

    # 函数应该先定义后使用。
    import time
    def timmer(func): # 定义函数就相当于定义变量名,就相当于把函数的代码绑定到一个名字上面了。 #1,定义变量名 #3 func值就是index
        def wrapper(): #4 开始执行timmer里面的代码,只要碰到def就跟定义变量名一样,它里边定义的代码全不用管,只要不执行就不用管它。#7
            start_time=time.time() #8
    #        print(func) 
            func() #9 func就是最原始的index
            stop_time=time.time() #14
            print('run time is %s' %(stop_time-start_time)) #15
        return wrapper #5 return wrapper 就是return wrapper的内存地址
    
    # index=timmer(index)  
    @timmer #2 timmer要运行timmer(index),所以要跳回去 #10
    def index(): #11
        time.sleep(3) #12
        print('welcome to oldboy') #13
    index() #6 index就是wrapper函数,wrapper是一个闭包函数,里边包含了一个状态,就是func。

    (2): # 第一次是home,第二次是home("name")

    输出:
    welcome to dragon home page
    run time is 2.0001144409179688
    egon 123
    run time is 0.0
    ------------
    run time is 0.0

    注意:传参数,需要加上*args,**kwargs

    (3):

    输出:
    my_max function
    run time is 0.0
    -------- 2

    注意:如果原函数需要有返回值,则装饰器也需要设置return res。完整正确的无参装饰器写法就是以上写法。 

    有参装饰器:

    (1): #第一步是函数()的效果,第二步是@auth的效果

     输出:还他妈的不会玩
    
    #有参函数执行流程
    def auth2(auth_type): #1 #3
        def auth(func): #4 #6
            def wrapper(*args,**kwargs): #7 #10
                if auth_type == 'file': #11
                    name=input('username: ')
                    password=input('password: ')
                    if name == 'zhejiangF4' and password == 'sb945':
                        print('auth successfull')
                        res=func(*args,**kwargs)
                        return res
                    else:
                        print('auth error')
                elif auth_type == 'sql': #12
                    print('还他妈不会玩') #13
            return wrapper #8
        return auth #5
    
    @auth2(auth_type='sql') #2
    def index():
        print('welcome to inex page')
    
    # @auth
    # def home():
    #     print('welcome to home page')
    index() #9

    多个装饰器:

    #多个无参装饰器:
    # @aaa
    # def func():
    #     pass
    #
    # func=aaa(func)
    
    # @ccc
    # @bbb
    # @aaa
    # def func():
    #     pass
    #
    # func=ccc(bbb(aaa(func)))
    
    #多个有参装饰器
    # @ccc('c')
    # @bbb('b')
    # @aaa('a')
    # def func():
    #     pass
    #
    # func=ccc('c')(bbb('b')(aaa('a')(func)))

    多个装饰器应用:

    import time
    current_login={'name':None,'login':False}
    
    def timmer(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            res=func(*args,**kwargs)  #my_max(1,2)
            stop_time=time.time()
            print('run time is %s' %(stop_time-start_time))
            return res
        return wrapper
    
    def auth2(auth_type='file'):
        def auth(func):
            # print(auth_type)
            def wrapper(*args,**kwargs):
                if current_login['name'] and current_login['login']:
                    res=func(*args,**kwargs)
                    return res
                if auth_type == 'file':
                    name=input('username: ')
                    password=input('password: ')
                    if name == 'luchuan' and password == '123':
                        print('auth successfull')
                        res=func(*args,**kwargs)
                        current_login['name']=name
                        current_login['login']=True
                        return res
                    else:
                        print('auth error')
                elif auth_type == 'sql':
                    print('还他妈不会玩')
            return wrapper
        return auth
    
    @timmer
    @auth2(auth_type='file') #@auth  #index=auth(index)
    def index():
        print('welcome to inex page')
    
    @auth2()
    def home():
        print('welcome to home page')
    
    
    
    #调用阶段
    index()
    home()

    装饰器帮助信息补充:

    import time
    from functools import wraps
    def timmer(func):
        @wraps(func)
        def wrapper(*args,**kwargs):
            'sssssssssssss' # 不加wraps,就会返回'sssssss'帮助信息
            start_time=time.time()
            func(*args,**kwargs) #home(name)
            stop_time=time.time()
            print('run time is %s' %(stop_time-start_time))
        return wrapper
    
    
    @timmer
    def func(x):
        'func test'
        print(x)
    
    func(1)
    print(func.__doc__)  # 查看帮助信息的两种方式
    # print(help(func))
    
    #不加wraps,输出sssssssss
    #加上wraps,则输出:from test

    二 装饰器需要遵循的原则

    1.不修改被装饰函数的源代码(开放封闭原则)

    2.为被装饰函数添加新功能后,不修改被修饰函数的调用方式

    三 实现装饰器知识储备

    装饰器=高阶函数+函数嵌套+闭包

    装饰器:一个外部函数、一个内部函数、一个return 、如果是有参装饰器,外部再包一层函数。

    四 高阶函数

    高阶函数定义:
    1.函数接收的参数是一个函数名

    2.函数的返回值是一个函数名

    3.满足上述条件任意一个,都可称之为高阶函数

    def foo():
        print('我的函数名作为参数传给高阶函数')
    def gao_jie1(func):
        print('我就是高阶函数1,我接收的参数名是%s' %func)
        func()
    
    def gao_jie2(func):
        print('我就是高阶函数2,我的返回值是%s' %func)
        return func
    
    gao_jie1(foo)
    gao_jie2(foo)
    
    高阶函数示范
    高阶函数示范
    #高阶函数应用1:把函数当做参数传给高阶函数
    import time
    def foo():
        print('from the foo')
    
    def timmer(func):
        start_time=time.time()
        func()
        stop_time=time.time()
        print('函数%s 运行时间是%s' %(func,stop_time-start_time))
    timmer(foo)
    #总结:我们确实为函数foo增加了foo运行时间的功能,但是foo原来的执行方式是foo(),现在我们需要调用高阶函数timmer(foo),改变了函数的调用方式
    
    把函数当做参数传给高阶函数
    把函数当做参数传给高阶函数
    #高阶函数应用2:把函数名当做参数传给高阶函数,高阶函数直接返回函数名
    import time
    def foo():
        print('from the foo')
    
    def timmer(func):
        start_time=time.time()
        return func
        stop_time=time.time()
        print('函数%s 运行时间是%s' %(func,stop_time-start_time))
    foo=timmer(foo)
    foo()
    #总结:我们确实没有改变foo的调用方式,但是我们也没有为foo增加任何新功能
    
    函数返回值是函数名
    函数返回值是函数名

    高阶函数总结
    1.函数接收的参数是一个函数名
      作用:在不修改函数源代码的前提下,为函数添加新功能,
      不足:会改变函数的调用方式
    2.函数的返回值是一个函数名
      作用:不修改函数的调用方式
      不足:不能添加新功能

    五 函数嵌套

    def father(name):
        print('from father %s' %name)
        def son():
            print('from son')
            def grandson():
                print('from grandson')
            grandson()
        son()
    
    father('林海峰')

    六 闭包

    '''
    闭包:在一个作用域里放入定义变量,相当于打了一个包
    '''
    def father(name):
        def son():
            # name='alex'
            print('我爸爸是 [%s]' %name)
            def grandson():
                # name='wupeiqi'
                print('我爷爷是 [%s]' %name)
            grandson()
        son()
    
    father('林海峰')

    七 无参装饰器

    无参装饰器=高级函数+函数嵌套

    基本框架

    1 #这就是一个实现一个装饰器最基本的架子
    2 def timer(func):
    3     def wrapper():
    4         func()
    5     return wrapper

    加上参数

    1 def timer(func):
    2     def wrapper(*args,**kwargs):
    3         func(*args,**kwargs)
    4     return wrapper

    加上功能

    1 import time
    2 def timer(func):
    3     def wrapper(*args,**kwargs):
    4         start_time=time.time()
    5         func(*args,**kwargs)
    6         stop_time=time.time()
    7         print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
    8     return wrapper

     加上返回值

    1 import time
    2 def timer(func):
    3     def wrapper(*args,**kwargs):
    4         start_time=time.time()
    5         res=func(*args,**kwargs)
    6         stop_time=time.time()
    7         print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
    8         return res
    9     return wrapper

    使用装饰器

    1 def cal(array):
    2     res=0
    3     for i in array:
    4         res+=i
    5     return res
    6 
    7 cal=timer(cal)
    8 cal(range(10))

    语法糖@

    1 @timer  #@timer就等同于cal=timer(cal)
    2 def cal(array):
    3     res=0
    4     for i in array:
    5         res+=i
    6     return res
    7 
    8 cal(range(10))

    八 装饰器应用示例

    user_list=[
        {'name':'alex','passwd':'123'},
        {'name':'linhaifeng','passwd':'123'},
        {'name':'wupeiqi','passwd':'123'},
        {'name':'yuanhao','passwd':'123'},
    ]
    
    current_user={'username':None,'login':False}
    
    def auth_deco(func):
        def wrapper(*args,**kwargs):
            if current_user['username'] and current_user['login']:
                res=func(*args,**kwargs)
                return res
            username=input('用户名: ').strip()
            passwd=input('密码: ').strip()
    
            for index,user_dic in enumerate(user_list):
                if username == user_dic['name'] and passwd == user_dic['passwd']:
                    current_user['username']=username
    
                    current_user['login']=True
                    res=func(*args,**kwargs)
                    return res
                    break
            else:
                print('用户名或者密码错误,重新登录')
    
        return wrapper
    
    @auth_deco
    def index():
        print('欢迎来到主页面')
    
    @auth_deco
    def home():
        print('这里是你家')
    
    def shopping_car():
        print('查看购物车啊亲')
    
    def order():
        print('查看订单啊亲')
    
    print(user_list)
    # index()
    print(user_list)
    home()
    
    无参装饰器
    无参装饰器
    user_list=[
        {'name':'alex','passwd':'123'},
        {'name':'linhaifeng','passwd':'123'},
        {'name':'wupeiqi','passwd':'123'},
        {'name':'yuanhao','passwd':'123'},
    ]
    
    current_user={'username':None,'login':False}
    def auth(auth_type='file'):
        def auth_deco(func):
            def wrapper(*args,**kwargs):
                if auth_type == 'file':
                    if current_user['username'] and current_user['login']:
                        res=func(*args,**kwargs)
                        return res
                    username=input('用户名: ').strip()
                    passwd=input('密码: ').strip()
    
                    for index,user_dic in enumerate(user_list):
                        if username == user_dic['name'] and passwd == user_dic['passwd']:
                            current_user['username']=username
                            current_user['login']=True
                            res=func(*args,**kwargs)
                            return res
                            break
                    else:
                        print('用户名或者密码错误,重新登录')
                elif auth_type == 'ldap':
                    print('巴拉巴拉小魔仙')
                    res=func(*args,**kwargs)
                    return res
            return wrapper
        return auth_deco
    
    
    #auth(auth_type='file')就是在运行一个函数,然后返回auth_deco,所以@auth(auth_type='file')
    #就相当于@auth_deco,只不过现在,我们的auth_deco作为一个闭包的应用,外层的包auth给它留了一个auth_type='file'参数
    @auth(auth_type='ldap')
    def index():
        print('欢迎来到主页面')
    
    @auth(auth_type='ldap')
    def home():
        print('这里是你家')
    
    def shopping_car():
        print('查看购物车啊亲')
    
    def order():
        print('查看订单啊亲')
    
    # print(user_list)
    index()
    # print(user_list)
    home()
    
    带参装饰器
    带参装饰器

    参考链接:http://www.cnblogs.com/linhaifeng/articles/6140395.html

    参考链接:http://www.cnblogs.com/yuanchenqi/articles/5828233.html#3503895

  • 相关阅读:
    PHP 函数
    MariaDB——(三) MariaDB 10.0.15 standard replication主从复制搭建
    MariaDB——(二) MariaDB 10.0.15 日志文件—undo 日志
    MariaDB——(一)CentOS 6.5 下 MariaDB 10.0.15 YUM 安装
    虚拟机中的linux系统文件突然全部变成只读的问题
    复制虚拟机vmware centos搭建集群节点过程中网络配置eth0和eth1遇到的问题以及NAT模式下虚拟机静态IP配置方法
    WMware 中CentOS系统Hadoop 分布式环境搭建(一)——Hadoop安装环境准备
    关于Oracle字符集在dmp文件导入导出中的乱码影响
    VMware 打开虚拟机的时候提示 internal error 内部错误 遇到这个问题时我的解决方法
    ORACLE 存储过程中保存用户自定义异常信息的一种方式
  • 原文地址:https://www.cnblogs.com/luchuangao/p/6685571.html
Copyright © 2020-2023  润新知