zoukankan      html  css  js  c++  java
  • Python装饰器

    装饰器

    知识储备

    • 定义函数未被调用,函数内部不执行
    • 函数名代指整个函数

    例1:

    def f1():
        print("123")
    
    
    def f1():
        print("456")
    
    f1()
    
    #输出
    456

    例2:

    def f2():
        print("123")
    
    
    def f3(xxx):
        xxx()
    
    f3(f2)
    
    #输出
    123

     装饰器流程分析:

      写代码要遵循开放封闭原则,虽然在这个原则适用于面向对象开发,但是也适用于函数式编程,简单来说,它规定已经实现功能的代码不允许被修改,但是可以被扩展,即:

    • 封闭:已实现的功能代码块
    • 开放:对扩展开发
    def outer(func):
        def inner():
            print("log")
            return func()
        return inner
    
    
    @outer
    def f1():
        print("F1")

      def outer(func):...

        # @ + 函数名
         # 功能:
         # 1.自动执行outer函数并且将其下面的函数名f1当作参数传递
         # 2.将outer函数的返回值重新赋值给f1
      @outer
      def f1():
        print("F1")

    传递参数:

    例1、传递一个参数:

    # s1.py #
    def outer(func):
        def inner(a):
            print("before")
            r = func(a)
            print("after")
            return r
        return inner
    
    @outer
    def f1(arg):
        print(arg)
        return "fuck you"
    
    
    # s2.py #
    import s1
    
    ret = s2.f1('fafafa')
    print("return",ret)
    
    # 输出
    before
    fafafa
    after
    return fuck you

    例2、传递多个参数

    传递多个参数通过*args和**kwargs

    def outer(func):
        def inner(*args,**kwargs):
            print("before")
            r = func(*args,**kwargs)
            print("after")
            return r
        return inner
     
    @outer
    def f1(arg):
        print(arg)
        return "fuck you"

    多层装饰器:

    一个函数可以被多个装饰器装饰,用户从最外层开始逐层调用,返回值则是从最里层逐层向外返回。

    下面这个例子就是通过多层装饰器来实现用户登录和权限验证:

    USER_INFO = {}
    
    
    def check_login(func):
        def inner(*args, **kwargs):
            if USER_INFO.get("is_login",None):
                ret = func(*args, **kwargs)
                return ret
            else:
                print("请登录")
        return inner
    
    
    def check_admin(func):
        def inner(*args, **kwargs):
            if USER_INFO.get('user_type',None) == 2:
                ret = func(*args, **kwargs)
                return ret
            else:
                print("无权查看")
        return inner
    
    
    @check_login
    @check_admin
    def index():
        """
        管理员用户
        :return:
        """
        print("index")
    
    
    @check_login
    def home():
        """
        普通用户的登录
        :return:
        """
        print("home")
    
    
    def login():
        user = input("请输入用户名:")
        if user == "admin":
            USER_INFO['is_login'] = True
            USER_INFO['user_type'] = 2
        else:
            USER_INFO['is_login'] = True
            USER_INFO['user_type'] = 1
    
    
    def main():
        while True:
            inp = input("1.登录;2.查看信息;3.超级管理员管理 
     >>>")
            if inp == "1":
                login()
            elif inp == "2":
                home()
            elif inp == "3":
                index()
    
    main()

    带参数的装饰器:

    还有更牛逼的装饰器吗?我们来看下面的例子

    #!/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'

    functools.wraps

    上述的装饰器虽然已经完成了其应有的功能,即:装饰器内的函数代指了原函数,注意其只是代指而非相等,原函数的元信息没有被赋值到装饰器内部。例如:函数的注释信息

    def outer(func):
        def inner(*args, **kwargs):
            print(inner.__doc__)  # None
            return func()
        return inner
    
    @outer
    def function():
        """
        asdfasd
        :return:
        """
        print('func')
    

    如果使用@functools.wraps装饰装饰器内的函数,那么就会代指元信息和函数。

    def outer(func):
        @functools.wraps(func)
        def inner(*args, **kwargs):
            print(inner.__doc__)  # None
            return func()
        return inner
    
    @outer
    def function():
        """
        asdfasd
        :return:
        """
        print('func')
    

      

  • 相关阅读:
    js中return的作用及用法
    js数组、字符串常用方法
    关于Ajax知识点小节
    关于跨域,同源策略小节
    Javascript模块化编程(三):require.js的用法【转】
    Javascript模块化编程(二):AMD规范【转】
    Javascript模块化编程(一):模块的写法【转】
    AJAX——核心XMLHttpRequest对象
    clientX,screenX,pageX,offsetX的异同 【转载】
    原生js获取鼠标坐标方法全面讲解:clientX/Y,pageX/Y,offsetX/Y,layerX/Y,screenX/Y【转】
  • 原文地址:https://www.cnblogs.com/Bourbon-tian/p/6137787.html
Copyright © 2011-2022 走看看