装饰器 decorator

来源:互联网 发布:unity3d工程师笔试题 编辑:程序博客网 时间:2024/05/16 10:10

环境:
mac osx , python3.5

首先看例子
在前面的描述器与静态方法,类方法中:
对于例子

class B(object):    @staticmethod    def foo():        pass

上面定义的类方法,使用的是装饰器的语法,@ 符号被称为 语法糖(syntactic sugar)。
以上类实现的效果等同于:

class B(object):    def foo():        pass    foo = staticmethod(foo)

从形式上看,第一个定义中函数名出现的次数小于第二种定义,使用装饰器明显使得定义简单。以上也是装饰器的工作原理。

闭包

如果定义如下函数:

def make_printer(word):    def inner():        print(word)    return innerdoge = make_printer('such wow!')doge()#such wow!

在python中一切皆对象。包括函数:

def f():    passtype(f)#<class 'function'>isinstance(f, object)#Truef.a =40f.a#40

也就是说函数能被像对象那样传递使用,它们可以被赋值给变量,在函数中作为参数传递。函数可以创建函数-这也是闭包的创建。

闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,闭包是由函数和与其相关的引用环境组合而成的实体。(一个函数和它的环境变量合在一起,就构成了一个闭包(closure)。在Python中,所谓的闭包是一个包含有环境变量取值的函数对象。)

根据概念也就是inner()/doge() 函数与 word 变量构成闭包。

装饰器作为闭包

根据装饰器的工作原理,可以将上面的例子写成 装饰器+闭包 形式:

def make_printer(func):    def inner(*arg, **kwargs):        func(*arg, **kwargs)    return inner@make_printerdef doge(word):    print(word)doge("such wow!")#such wow!

也就是:

def make_printer(func):    def inner(*arg, **kwargs):        func(*arg, **kwargs)    return innerdef doge(word):    print(word)doge= make_printer(doge)doge("such wow!")#such wow!doge.__name__#inner

__name__ 以及 __doc__属性值不对。参考使用 functools 以及 wrapt 的使用。

计数

def count(wrapped):    def inner(*wargs, **kwargs):        inner.counter += 1        return wrapped(*args, **kwargs)    inner.counter = 0 #如果不在函数调用前提前给函数对象添加属性就会出错    return inner@countdef doge():    pass

赋值的装饰器

def skip_if(conditional, message):    def dec(wrapped):        def inner(*args, **kwargs):            if not conditional:                # Execute the function as normal                return wrapped(*args, **kwargs)            else:                # Skip the function, print the message                print(message)        return inner    return dec@skip_if(True, 'Will not execute, because I hate doge')def doge():    print('very print')doge()# Will not execute, because I hate doge

上面的情况可能理解有些困难。可以先看如下的改写:

def skip_if(conditional, message):    def dec(wrapped):        def inner(*args, **kwargs):            if  conditional:                # Execute the function as normal                return wrapped(*args, **kwargs)            else:                # Skip the function, print the message                print(message)        return inner    return dec#@skip_if(True, 'Will not execute, because I hate doge')def doge():    print('very print')doge = skip_if(True, 'Will not execute, because I hate doge')doge()

执行上面的程序,出线如下错误:
ypeError: dec() takes exactly 1 argument (0 given)

也就是说dec要赋值。那么可以把上面装饰器的执行流程理解为:
首先将 True, 'Will not execute, because I hate doge'分别赋值给conditional, message,然后把doge 函数对象赋值给下一个函数的参数wrapped `

参考文章

A guide to python decorators

https://www.codeschool.com/blog/2016/05/12/a-guide-to-python-decorators/

Python中的闭包

http://www.2cto.com/kf/201507/420734.html

0 0
原创粉丝点击