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

    一、什么是装饰器

      装饰器自身就是一个函数,它是在函数上调用的装饰,也可以说用一个函数(装饰器)来”装饰”另一个函数。在代码中以@表示,很明显的是在某个函数之上出现了@,就说明装饰器装饰了其函数。重点来了,那么它为什么叫做装饰器呢?

    >>> import time
    >>> def extend_login(func):
    >>>     def timestamp(*args,**kwargs):
    >>>         print (time.ctime())    #打印当前系统时间
    >>>         func(*args,**kwargs)
    >>>     return timestamp    #注意这里不能加括号,因为return的是timestamp的内存地址,不可写为timestamp()
    >>> 
    >>> @extend_login
    >>> def login(username):
    >>>     print ("%s login system" % username)
    >>> 
    >>> login('Stanley')

      以上代码中,extend_login 就是装饰器的名称,它是一个函数,接收func作为这个函数的参数。因为在执行exntend_login函数的时候,并没有立即执行timestamp函数,而是将timestamp生成内存地址(图1),下一步直接return了timestamp的内存地址到login函数,此时的login函数已经不再是原来的它,经过了extend_login函数的装饰,已经变为了login = extend_login(login),这里的login是其内存地址;最后执行执行login函数(也就是timestamp函数。所谓装饰器是指在执行func函数之前,又执行了其他的操作(打印当前系统时间),所以说起到了装饰func函数的作用,其功能是在用户登陆之前,打印当前系统时间,这就是一个装饰器。

    999

    图1

    二、如何使用装饰器

      装饰器到底有什么使用的场景能让它物有所用呢,大多数的场景是在函数不修改原有函数的基础上,在其外部扩展一个函数的行为,修改函数或扩展原有功能;另一方如果这个功能可以被使用在很多函数上,或是函数并不是自己实现,那可以写个装饰器来实现这些功能,而不用重复编写,减少代码的冗余度。

    >>> @extend_login
    >>> def login():
    >>>     pass

      在装饰器使用过程中,@extend_login含义是调用名为exntend_login的装饰器(其实就是个函数)来装饰login函数,那么按照如上调用等价于:

    >>> login = extend_login(login)    #这里括号内的login没有(),仅仅是吧login的内存地址当做参数传递给extend_login装饰器(函数)

    三、装饰器内传递参数

      在给装饰器内传递参数的时候,需要注意的是在timestamp函数内,要写多个接收参数和接收任意类型参数,也就是*args和**kwargs;如果这里没有指定接收参数,那么在login函数向装饰器内传递参数会出现报错。

    >>> import time
    >>> def extend_login(func):
    >>>     def timestamp():    #没有参数会报错
    >>>         print (time.ctime())
    >>>         func()    #没有参数会报错
    >>>     return timestamp
    >>> 
    >>> @extend_login
    >>> def login(username):
    >>>     print ("%s login system" % username)
    >>> 
    >>> login('Stanley')
    TypeError: timestamp() takes no arguments (1 given)

      在装饰器调用中,会把login函数的参数传递给装饰器(图2)

    869426-20160201153530366-1693317262

    图2

    四、完整示例

    >>> import time
    >>> def extend_login(func):
    >>>     def timestamp(*args,**kwargs):
    >>>         print (time.ctime())
    >>>         func(*args,**kwargs)
    >>>     return timestamp
    >>> 
    >>> @extend_login
    >>> def login(username):
    >>>     print ("%s login system" % username)
    >>> 
    >>> login('Stanley')
    
    Mon Feb 01 11:29:40 2016
    Stanley login system
  • 相关阅读:
    让SiteMapDataSource能选择特定的SiteMap文件
    程序员之路──如何学习C语言(转载)
    Sql Server 2005 Express使用命令工具无法连接问题
    移远公司 NBIoT模块AT指令详细解释
    Excel自动化技术
    解析HTTP报文头
    SOAP报文下发
    双缓冲队列,生产者消费者模式
    夸孩子少用“你真棒”,教你如何夸孩子
    C++面试题相关
  • 原文地址:https://www.cnblogs.com/stefan-liu/p/5176442.html
Copyright © 2011-2022 走看看