zoukankan      html  css  js  c++  java
  • 带参数的装饰器

    https://blog.csdn.net/e15273/article/details/78617498

    回顾普通的装饰器

    def outer(func):
        def wrapper(*args,**kwargs): #装饰后的方法
            print("before func")
            wrapper_result=func(*args,**kwargs)
            print("after func")
            return wrapper_result
        return wrapper

    def foo(a,b):
        return a+b

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11

    >>> foo=outer(foo)
    >>> foo(2,2)
    before func
    after func
    4

        1
        2
        3
        4
        5

    与下面使用@outer修饰等同

    >>> @outer
    ... def foo(a,b):
    ...     return a+b
    ...
    >>> foo(1,3)
    before func
    after func
    4

        1
        2
        3
        4
        5
        6
        7
        8

    functools.wraps

    我们在使用 Decorator 的过程中,难免会损失一些原本的功能信息。
    也就是说,原函数的属性失效了。
    如果想要保留原函数的属性,就可以用到functools.wraps了。

    >>> print(foo.__name__)
    wrapper

        1
        2

    而functools.wraps 则可以将原函数对象的指定属性复制给包装函数对象, 默认有 module、name、doc,或者通过参数选择。代码如下:

    from functools import wraps
    def outer(func):
        @wraps(func)
        def wrapper(*args,**kwargs):
            print("before func")
            wrapper_result=func(*args,**kwargs)
            print("after func")
            return wrapper_result
        return wrapper

    @outer
    def foo(a,b):
        return a+b

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13

    >>> print(foo.__name__)
    foo

        1
        2

    带参数的装饰器

    def outer(outer_args):
        def middle(func):
            def wrapper(*args,**kwargs):
                print("before func")
                print("use args: "+outer_args)
                wrapper_result=func(*args,**kwargs)
                print("after func")
                return wrapper_result
            return wrapper
        return middle

    @outer("hello")
    def foo(a,b):
        return a+b

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14

    >>> res=foo(3,3)
    before func
    use args: hello
    after func
    >>> res
    6

        1
        2
        3
        4
        5
        6

    带参数修饰器效果等价于:

    >>> foo=outer("hello")(foo)

        1

    这种语法有点奇怪,下面来解释这种语法:
    一般而言,调用一个函数是加一个括号。如果看见括号后还有一个括号,说明第一个函数返回了一个函数,如果后面还有括号,说明前面那个也返回了一个函数。以此类推。例子如下:

    def fun(args_outer):
        print("now in the outer"+" "+args_outer);
        def inner_fun(args_inner):
            print("now in the inner"+" "+args_inner);
        return inner_fun;

        1
        2
        3
        4
        5
        6

    >>> from test import *
    >>> fun('hello')('world')
    now in the outer hello
    now in the inner world

        1
        2
        3
        4

    这叫做python method chaining

    类似的也有类后面多个括号连续写的代码写法:

    class add(int):
        def __call__(self,n):

            return add(self+n)

    print add(1)(2)(3)

        1
        2
        3
        4
        5
        6

    1、首先要理解这个call方法,当类中定义了call方法后,类的实例对象可以带括号调用。
    class_x(arguments)<=>class_ x.__call__(arguments)
    2、add(1) 是你类的实例对象。
    由于类中定义了方法__call__ 所以你的实例对象
    add(1)(2) 是调用__call__方法,__call__方法要参数,所以这里传了一个实际参数2。

    在这里又要讲讲python特殊函数 __call__()

    在Python中,函数其实是一个对象,由于函数可以被调用,所以,函数对象被称为可调用对象。一个类实例也可以变成一个可调用对象,只需要实现一个特殊方法__call__()。我们把 Person 类变成一个可调用对象:

    class Person(object):
        def __init__(self, name, gender):
            self.name = name
            self.gender = gender
        def __call__(self, friend):
            print 'My name is %s.' % self.name
            print 'My friend is %s.' % friend

        1
        2
        3
        4
        5
        6
        7

    现在可以对 Person 实例直接调用:

    >>> p = Person('Bob', 'male')
    >>> p('Tim')
    My name is Bob.
    My friend is Tim.
    ---------------------  
    作者:Avalonist  
    来源:CSDN  
    原文:https://blog.csdn.net/e15273/article/details/78617498  
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    重装fedora17之后的一些配置
    virtualbox中安装3D支持
    Win8下Qualcomm Atheros AR9285网卡改mac
    Android应用【世界杯知识答题】的界面设计经验
    Android应用【世界杯风云2010】的界面设计经验小结
    html基础知识层级选择器
    html基础知识,两种引入css样式方式
    html结构伪类选择器
    html基础知识表格标签(form,input)
    html基础知识(三种颜色写法)
  • 原文地址:https://www.cnblogs.com/fengff/p/10641850.html
Copyright © 2011-2022 走看看