Close

[python] 装饰器学习

很多python的代码都带有装饰器=。=
现在不学以后也要学
学一下装饰器

闭包

在学装饰器之前先看看python的闭包

在一些语言中,在函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包。闭包可以用来在一个函数与一组“私有”变量之间创建关联关系。在给定函数被多次调用的过程中,这些私有变量能够保持其持久性。
—— 维基百科)

def make_printer(msg):
    def printer():
        print msg  # 夹带私货(外部变量)
    return printer  # 返回的是函数,带私货的函数

printer = make_printer('Foo!')
printer()

闭包就是当某个函数被当成对象返回时,夹带了外部变量,就形成了一个闭包。

而如果内部函数里引用了外部函数里定义的对象(甚至是外层之外,但不是全局变量),那么此时内部函数就被称为闭包函数。闭包函数所引用的外部定义的变量被叫做自由变量。闭包从语法上看非常简单,但是却有强大的作用。闭包可以将其自己的代码和作用域以及外部函数的作用结合在一起。下面给出一个简单的闭包的例子:

def count(a):
    b = 1
    def sum():
        c = 1
        return a + c  # a是自由变量
    return sum

print count(a = 2)() # 3

装饰器

python装饰器本质上就是一个函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外的功能,装饰器的返回值也是一个函数对象(函数的指针)

装饰器的属性

  • 实质: 是一个函数
  • 参数:是你要装饰的函数名(并非函数调用)
  • 返回:是装饰完的函数名(也非函数调用)
  • 作用:为已经存在的对象添加额外的功能
  • 特点:不需要对对象做任何的代码上的变动

python装饰器有很多经典的应用场景,比如:插入日志、性能测试、事务处理、权限校验等。装饰器是解决这类问题的绝佳设计。并且从引入中的列子中我们也可以归纳出:装饰器最大的作用就是对于我们已经写好的程序,我们可以抽离出一些雷同的代码组建多个特定功能的装饰器,这样我们就可以针对不同的需求去使用特定的装饰器,这时因为源码去除了大量泛化的内容而使得源码具有更加清晰的逻辑

装饰器也分为函数装饰器和类装饰器

在python2.4之前的装饰器是这样的

def debug(func):
    def wrapper():
        print "[DEBUG]: enter {}()".format(func.__name__)
        return func()
    return wrapper

def say_hello():
    print "hello!"

say_hello = debug(say_hello)  # 添加功能并保持原函数名不变

其实装饰器的原理就跟这个差不多他返回的就是wrapper 会把原来的覆盖了
-w468

跟现在的装饰器的意思是一样的

def debug(func):
    def wrapper():
        print "[DEBUG]: enter {}()".format(func.__name__)
        return func()
    return wrapper

@debug
def say_hello():
    print "hello!"

只不过更加简便少了一步赋值的步骤

函数装饰器

上面的都是函数装饰器

def debug(func):
    def wrapper():
        print "[DEBUG]: enter {}()".format(func.__name__)
        return func()
    return wrapper

@debug
def say_hello():
    print "hello!"

say_hello()

类装饰器

装饰器函数其实是这样一个接口约束,它必须接受一个callable对象作为参数,然后返回一个callable对象。在Python中一般callable对象都是函数
只要当前的类中有一个__call__函数就可以让该对象编程callable对象
只要用__init__来初始化, __call__来返回函数就可以了

class debug():
    def __init__(self, func):
        self.func = func

    def __call__(self):
        print "[DEBUG]: enter {func}()".format(
            func=self.func.__name__)
        return self.func()
@debug
def say_hello():
    print "say hello!"

say_hello()

这样就好了
跟原来的函数装饰器差不多

参考链接

https://betacat.online/posts/2016-10-23/python-closure/
https://www.cnblogs.com/cicaday/p/python-decorator.html

Leave a Reply

Your email address will not be published. Required fields are marked *