python中的装饰器

一颗语法糖——装饰器
理论不去管,只管能办事:

1.  我要让一个函数在执行的时候,去做一些事情,比如,我要看看这些函数是不是有docstring,将这个功能拿出来,定义一个装饰器:
def showmedoc(func):
     if func.__doc__:
          print 'has doc'
     else:
          print 'no doc'
     return func                                      #别装饰了之后把人家原来的函数给盖了,除了需要的情况...
和装饰设计模式异曲同工,差不多就是一个东西,下面就用它来办事情 了:

@showmedoc
def f1():
    '''i have doc'''
    pass

@showmedoc
def f2():
     pass

执行结果:
>>> 
has doc 
no doc
>>> 

现在的情况是,我们在代码里并没有调用f1,f2,我们知识装饰了一下他们。却有输出,说明在执行的时候,解释器先扫描被装饰的函数,装饰好了,然后就等着函数执行了。

2.再看看这样的情况:

def say_hi():
    print 'hello'


def showmedoc(func):
    if func.__doc__:
        print 'has doc '
    else:
        print 'no doc'
    return say_hi

@showmedoc
def f1():
    '''hello world'''
    print "hihi"


f1()

得到输出:
>>> 
has doc 
hello
>>> 

很明显,我们改变了程序的入口!我们知道,第一行是在f1定义时,被装饰的时候输出的,以判断她是不是有docstring。然后呢,我们改变了程序的入口到say_hi。我们原来的函数实现跟我们说88了,取而代之的是say_hi。

3。根据上下文环境来改变程序的入口:

实际应用中,会遇到这样的情况:我们根据用户是否已经登陆来改变程序的执行流程。
用况:我们的某个处理过程需要用户的登陆信息,用户不登陆这个处理是没有办法继续的。那怎么去保证用户登陆呢?装饰一下,给函数加个身份验证的功能呗。我们来模拟以下这个装饰器:
def login_required(func):
      如果用户登陆:
             什么都不做
      如果用户没有登陆:
            重定向到用户登陆窗口
      return func

 现在好了,只要你的处理过程需要用户的登陆信息,你就可以简单地装饰一下就可以了,而不用在每个处理过程里去写重复的代码了:
@login_required
def func():
      处理

这样将公共的功能提取出来;增强了代码的可读性。

4.带参数的装饰器

默认情况下,我们装饰一个函数的时候,这个函数对象就默认的参数是函数对象本身。但是我们需要传递多个参数该怎么办呢??
想当然地我们来了一个
def showmedoc(func,x):
    if func.__doc__:
        print 'has doc '
    else:
        print 'no doc'
    return say_hi
其他的都不改变。
我想当然地来了一个,所以当然不行了,在
@showmedoc
def f1():
    '''hello world'''
    print "hihi"
中,showmedoc只能接受一个参数,就是f1。而我们定义的装饰器却要接受两个参数,,所以不行。how to do ???
very well 
我们再套一曾试试:
def showmedoc(x):
    def xshowmedoc(func):
        if func.__doc__:
            print 'has doc ' * x
        else:
            print 'no doc' * x
        return say_hi
    return xshowmedoc

@showmedoc(2,f1)
def f1():
    '''hello world'''
    print "hihi"

执行结果:
>>> 
has doc has doc 
>>> 

我纳闷了,这个func参数是什么时候溜近来的,在我的装饰器局部变量里根本没有什么func啊??what happened ?/
def showmedoc(x,y,z):
    def xshowmedoc(func):
        if func.__doc__:
            print 'has doc ' * x
        else:
            print 'no doc' * x
        return say_hi
    return xshowmedoc

@showmedoc(2,5,6)
def f1():
    '''hello world'''
    print "hihi"

变成这样后依然可以正常执行。KO,我们可以断定了,外面这一层衣服就一提供参数的东东,其他的什么也不是了。真正干活的是里面的xshowmedoc:

def showmedoc(x,y,z):
    def xshowmedoc(func,x):
        if func.__doc__:
            print 'has doc ' * x
        else:
            print 'no doc' * x
        return say_hi
    return xshowmedoc

@showmedoc(2,5,6)
def f1():
    '''hello world'''
    print "hihi"
我在xshowmedoc中加了一个参数:
>>> 
Traceback (most recent call last):
  File "F:/deco.py", line 58, in <module>
    @showmedoc(2,5,6)
TypeError: xshowmedoc() takes exactly 2 arguments (1 given)
>>> 
显然是错误的,很显然,我们没有直接为xshowmedoc提供任何参数,可是它却说 (1 given),事情很清楚了,函数对象知道你穿的那件衣服只是一层摆设,它是与装饰器本身相关的,而我要把自己以身相许给真正干活的那位!当然就是xshowmedoc。

def showmedoc():
    def xshowmedoc(func):
        if func.__doc__:
            print 'has doc ' 
        else:
            print 'no doc'
        return say_hi
    return xshowmedoc

@showmedoc()
def f1():
    '''hello world'''
    print "hihi"

这 样也是对的,由次可见,无参数的装饰器只是一个特例。而是不是有参数,主要看是怎么用 了,你在用装饰器时后面有括号,就是有参数的,没有括号就是没有参数的。没有参数的很简单,就直接将 装饰的函数对象作为第一个参数传递给了装饰器 。如果有参数的话(应用的时候有括号),解释器明白这个是个带参数的装饰器 ,然后呢它就会把这个被装饰的函数对象作为这件衣服下定义的所有的函数的 第一个参数传递进去!!,这样就可以对函数对象进行操作了。可以证明一下我们的想法:
def showmedoc():
    def xshowmedoc(func):
        if func.__doc__:
            print 'has doc ' 
        else:
            print 'no doc'
        return say_hi
    def xshowmedoc2(func):
        if func.__doc__:
            print 'has doc my god' 
        else:
            print 'no my god'        
    return xshowmedoc2

@showmedoc()
def f1():
    '''hello world'''
    print "hihi"

输出:
>>> 
has doc my god
>>> 

从这里我们又可以看出,你可以有不同的装饰方案,可以根据条件来设置!!够强大吧!最关键的一点就是究竟是有参数还是没有参数是从应用的角度看的,而不是从定义的角度看的。从定义的角度看 ,装饰器必须有一个参数——被修饰的函数。

my god,究竟是怎么发生的呢?有参数的装饰器真是太难理解了。

从应用的地方看:@showmedoc(),其中
showmedoc()是个函数的调用,它返回什么,我的天,它不就是个装饰器吗,似曾相识啊,就是个无参数的装饰器啊,就是下面这个东西啊:
    def xshowmedoc2(func):
        if func.__doc__:
            print 'has doc my god' 
        else:
            print 'no my god'  

转了一个大圈圈又回来了!!我们仅仅是定义了一个返回装饰器的函数,然后调用这个函数我们就得到一个装饰器。showmedoc()不是装饰器,而是它返回的那个东西才是装饰器,showmedoc()仅仅就是为了传递参数而已。
其实再多看 一点,showmedoc()是什么,showmedoc又是什么????在python里带括号的就是调用。而不带的呢,就是函数对象。而装饰器是一个什么玩意儿?是一个函数对象!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
装饰器Python一种用于修改函数或类的行为的语法结构。它们允许在不修改原始代码的情况下,通过添加额外的功能来装饰函数或类。 装饰器实际上是一个函数,它接受一个函数作为输入,并返回一个新的函数作为输出。这个新的函数通常会在调用原始函数之前或之后执行一些额外的代码。 下面是一个简单的装饰器示例: ```python def decorator_function(original_function): def wrapper_function(): # 在调用原始函数之前执行额外的操作 print("Before the original function is called") # 调用原始函数 original_function() # 在调用原始函数之后执行额外的操作 print("After the original function is called") return wrapper_function @decorator_function def say_hello(): print("Hello!") # 调用经过装饰器修饰过的函数 say_hello() ``` 在上述示例,我们定义了一个名为`decorator_function`的装饰器函数。该装饰器接受一个名为`original_function`的函数作为参数,并返回一个新的函数`wrapper_function`。`wrapper_function`在调用原始函数之前和之后,分别打印了一些额外的信息。 通过在`say_hello`函数定义之前加上`@decorator_function`,我们将`say_hello`函数传递给了装饰器,并将装饰器返回的函数赋值给了`say_hello`。这样,当我们调用`say_hello`函数时,实际上是在调用经过装饰器修饰过的函数`wrapper_function`。 装饰器提供了一种灵活且可重复使用的方式来扩展函数的功能,比如添加日志记录、性能计时、输入验证等。在Python,还有一种更简洁的语法糖形式来使用装饰器,即使用`@`符号将装饰器应用到函数上,如上述示例的`@decorator_function`。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值