美文网首页大数据 爬虫Python AI Sqlpython每天一约
python 中面向切面编程AOP和装饰器

python 中面向切面编程AOP和装饰器

作者: Tim在路上 | 来源:发表于2018-10-01 09:55 被阅读1次

    相信学过java框架的对AOP应该是很熟悉了,那什么是面向切面编程AOP呢?

    AOP

    简言之、这种在运行时,编译时,类和方法加载时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。

    我们管切入到指定类指定方法的代码片段称为切面,而切入到哪些类、哪些方法则叫切入点。有了AOP,我们就可以把几个类共有的代码,抽取到一个切片中,等到需要时再切入对象中去,从而改变其原有的行为。

    优点是:这样的做法,对原有代码毫无入侵性

    装饰器

    装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。

    概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。

    要想明白装饰器首先要明白一个概念即函数即是对象。
    不明白的可以看看这篇文章

    python 函数的本质理解

    函数就是对象.因此,对象:

    • 可以赋值给一个变量
    • 可以在其他函数里定义
    • 函数可以返回另一个函数
    • 函数作为参数传递

    自己动手实现装饰器

    # 装饰器就是把其他函数作为参数的函数
    def my_new_decorator(a_function_to_decorate):
    
        # 在函数里面,装饰器在运行中定义函数: 包装.
        # 这个函数将被包装在原始函数的外面,所以可以在原始函数之前和之后执行其他代码..
        def the_wrapper_function():
    
            # 把要在原始函数被调用前的代码放在这里
            print "Before the function runs"
    
            # 调用原始函数(用括号)
            a_function_to_decorate()
    
            # 把要在原始函数调用后的代码放在这里
            print "After the function runs"
    
        # 在这里"a_function_to_decorate" 函数永远不会被执行
        # 在这里返回刚才包装过的函数
        # 在包装函数里包含要在原始函数前后执行的代码.
        return the_wrapper_function
    
    # 加入你建了个函数,不想修改了
    def a_stand_alone_function():
        print "I am a stand alone function, don't you dare modify me"
    
    a_stand_alone_function()
    #输出: I am a stand alone function, don't you dare modify me
    
    # 现在,你可以装饰它来增加它的功能
    # 把它传递给装饰器,它就会返回一个被包装过的函数.
    
    a_function_decorated = my_new_decorator(a_stand_alone_function)
    # 执行
    a_function_decorated()
    #输出s:
    #Before the function runs
    #I am a stand alone function, don't you dare modify me
    #After the function runs
    

    真实装饰器

    @my_new_decorator
    def another_stand_alone_function():
        print "Leave me alone"
    
    another_stand_alone_function()
    #输出:
    #Before the function runs
    #Leave me alone
    #After the function runs
    

    从这里可以看出@decorator就是下面的简写:

    another_stand_alone_function = my_new_decorator(another_stand_alone_function)
    

    在装饰器函数里传入参数

    def a_decorator_passing_arguments(function_to_decorate):
        def a_wrapper_accepting_arguments(arg1, arg2):
            print "I got args! Look:", arg1, arg2
            function_to_decorate(arg1, arg2)
        return a_wrapper_accepting_arguments
    
    # 当你调用装饰器返回的函数时,也就调用了包装器,把参数传入包装器里,
    # 它将把参数传递给被装饰的函数里.
    
    @a_decorator_passing_arguments
    def print_full_name(first_name, last_name):
        print "My name is", first_name, last_name
    
    print_full_name("Peter", "Venkman")
    # 输出:
    #I got args! Look: Peter Venkman
    #My name is Peter Venkman
    

    把参数传给装饰器

    # 装饰器就是一个'平常不过'的函数
    def my_decorator(func):
        print "I am an ordinary function"
        def wrapper():
            print "I am function returned by the decorator"
            func()
        return wrapper
    
    # 因此你可以不用"@"也可以调用他
    
    def lazy_function():
        print "zzzzzzzz"
    
    decorated_function = my_decorator(lazy_function)
    #输出: I am an ordinary function
    
    # 之所以输出 "I am an ordinary function"是因为你调用了函数,
    # 并非什么魔法.
    
    @my_decorator
    def lazy_function():
        print "zzzzzzzz"
    
    #输出: I am an ordinary function
    

    这里调用decorated_function()才会输出装饰器里面的方法,建一个装饰器.它只是一个新函数,去掉中间变量他就会变为真正的装饰器,那么如何去掉中间变量

    def decorator_maker_with_arguments(decorator_arg1, decorator_arg2):
    
        print "I make decorators! And I accept arguments:", decorator_arg1, decorator_arg2
    
        def my_decorator(func):
            # 这里传递参数的能力是借鉴了 closures.
            # 如果对closures感到困惑可以看看下面这个:
            # http://stackoverflow.com/questions/13857/can-you-explain-closures-as-they-relate-to-python
            print "I am the decorator. Somehow you passed me arguments:", decorator_arg1, decorator_arg2
    
            # 不要忘了装饰器参数和函数参数!
            def wrapped(function_arg1, function_arg2) :
                print ("I am the wrapper around the decorated function.\n"
                      "I can access all the variables\n"
                      "\t- from the decorator: {0} {1}\n"
                      "\t- from the function call: {2} {3}\n"
                      "Then I can pass them to the decorated function"
                      .format(decorator_arg1, decorator_arg2,
                              function_arg1, function_arg2))
                return func(function_arg1, function_arg2)
    
            return wrapped
    
        return my_decorator
    
    @decorator_maker_with_arguments("Leonard", "Sheldon")
    def decorated_function_with_arguments(function_arg1, function_arg2):
        print ("I am the decorated function and only knows about my arguments: {0}"
               " {1}".format(function_arg1, function_arg2))
    
    decorated_function_with_arguments("Rajesh", "Howard")
    #输出:
    #I make decorators! And I accept arguments: Leonard Sheldon
    #I am the decorator. Somehow you passed me arguments: Leonard Sheldon
    #I am the wrapper around the decorated function.
    #I can access all the variables
    #   - from the decorator: Leonard Sheldon
    #   - from the function call: Rajesh Howard
    #Then I can pass them to the decorated function
    #I am the decorated function and only knows about my arguments: Rajesh Howard
    

    看到了吗?我们用一个函数调用"@“

    几个例子

    def addTips(fun):
        def wrap(*arg,**kwargs):
            print("this is oper before")
            result = fun(*arg,**kwargs)
            #return result
            print("this is oper after")
            return result
        return wrap
    @addTips
    def add():
        print("进行添加的操作")
        
    add()
    
    this is oper before
    进行添加的操作
    this is oper after
    
    @addTips
    def add1(x,y):
        print(x+y)
    add1(2,6)
    
    this is oper before
    8
    this is oper after
    
    @addTips
    def add2(x,y):
        return x+y
    
    print(add2(2,3))
    
    this is oper before
    this is oper after
    5
    
    def addTips(i):
        def wrap1(fun):
            def wrap(*arg,**kwargs):
                print("this is oper before")
                result = 0
                if i > 10:
                    result = fun(*arg,**kwargs)
                else:
                    print("you not have any auth")
                #return result
                print("this is oper after")
                return result
            return wrap
        return wrap1
    
    @addTips(11)
    def add(x,y):
        print(x+y)
        
    add(2,3)
    
    this is oper before
    5
    this is oper after
    

    装饰器的知识点

    • 装饰器使函数调用变慢了.一定要记住.

    • 装饰器不能被取消(有些人把装饰器做成可以移除的但是没有人会用)所以一旦一个函数被装饰了.所有的代码都会被装饰.

    • Python自身提供了几个装饰器,像property, staticmethod.

    • Django用装饰器管理缓存和试图的权限.

    • Twisted用来修改异步函数的调用.

    相关文章

      网友评论

        本文标题:python 中面向切面编程AOP和装饰器

        本文链接:https://www.haomeiwen.com/subject/odtnoftx.html