美文网首页
Python装饰器

Python装饰器

作者: Ovie | 来源:发表于2017-01-16 23:51 被阅读0次

以前在IMOOC上学习的笔记。今晚整理下发出来。

要理解装饰器,先了解函数作用域和闭包。

  1. 函数作用域的查找顺序概括为:L -> E -> G -> B

    local 函数内部作用域

    enclosing 函数内部与内嵌函数之间

    global 全局作用域

    build-in 内置作用域

  2. 闭包(Closure)就是内部函数中对enclosing作用域的变量进行引用。举例:

    # -*-coding:utf-8 -*-
    
    def foo(func):
       def wrapper(x, y):
           if isinstance(x, int) and isinstance(y, int):
               return func(x, y)
           else:
               print 'Error'
               return None
       return wrapper
    
    def mysum(x, y):
        return x + y
    
    def mymul(x, y):
        return x * y
    
    mysum_ex = foo(mysum)
    print mysum_ex(1, 2)
    print mysum_ex.__closure__
    
    mymul_ex = foo(mymul)
    print mymul_ex(1, 2)
    print mymul_ex.__closure__
    

执行完foo函数,内部变量被回收,这里是func变量。但是在执行mysum_ex函数时,为什么访问得到func变量呢?因为闭包函数mysum_ex(实际上就是wrapper函数)有一个属性__closure__,存储着需要用到的enclosing 变量,即func变量。

闭包作用:封装和代码复用。怎么体现?

上面的mysum用来执行两个整数的加法,mymul用来执行两个整数的乘法。如果直接执行mysum('1', 2)mymul('1', 2)是会报错:TypeError: cannot concatenate 'str' and 'int' objects。所以需要添加判断参数是否是int类型的逻辑代码,如mysum函数

 def mysum(x, y):
     if isinstance(x, int) and isinstance(y, int):
         return x + y
     else:
         print 'Error'
         return None

mymul函数也需要相同的判断逻辑,所以利用闭包把这部分判断逻辑代码封装到wrapper()中,通过传递函数对象funcwrapper()函数内部使用,来决定到底使用加法操作还是乘法操作。这部分判断参数是否是int类型的逻辑代码达到了代码复用。

最后说装饰器。上面的闭包例子用装饰器来写:

# -*-coding:utf-8 -*-
import functools

def foo(func):
    @functools.wraps(func)
    def wrapper(x, y):
        if isinstance(x, int) and isinstance(y, int):
            return func(x, y)
        else:
            print 'Error'
            return None
    return wrapper


@foo
def mysum(x, y):
    return x + y

print mysum(1, 2)
print mysum('1', 2)

执行结果:

3
Error
None

对于装饰器的几点说明:

  1. 装饰器是对闭包的使用。

  2. 传递一个函数对象func给装饰器foofoo返回一个新的函数对象。对于闭包,就不一定要传递函数对象,可以传递其它类型的对象。如:

    # -*-coding:utf-8 -*-
    
    def set_passline(passline):
        def cmp(val):
            if val >= passline:
                print "pass"
            else:
                print "failed"
        return cmp
    
    f_100 = set_passline(60)
    print f_100.__closure__
    f_100(89)
    

    传递的是整数对象。

  3. def mysum(x, y):上边加@foo,是Python提供的语法。表示mysum这个函数对象作为func参数传递给foo(func)函数,再把foo函数返回的新函数对象赋给mysum

  4. 建议给装饰器里的wrapper加上@functools.wraps(func)装饰器。不加的时候mysum.__name__的值是wrapper,加上去值才是mysum

相关文章

  • 装饰器模式

    介绍 在python装饰器学习 这篇文章中,介绍了python 中的装饰器,python内置了对装饰器的支持。面向...

  • python中的装饰器

    python装饰器详解 Python装饰器学习(九步入门) 装饰器(decorator) 就是一个包装机(wrap...

  • [译] Python装饰器Part II:装饰器参数

    这是Python装饰器讲解的第二部分,上一篇:Python装饰器Part I:装饰器简介 回顾:不带参数的装饰器 ...

  • Python中的装饰器

    Python中的装饰器 不带参数的装饰器 带参数的装饰器 类装饰器 functools.wraps 使用装饰器极大...

  • Python进阶——面向对象

    1. Python中的@property   @property是python自带的装饰器,装饰器(decorat...

  • Python 装饰器填坑指南 | 最常见的报错信息、原因和解决方

    Python 装饰器简介装饰器(Decorator)是 Python 非常实用的一个语法糖功能。装饰器本质是一种返...

  • Python装饰器

    Python装饰器 一、函数装饰器 1.无参装饰器 示例:日志记录装饰器 2.带参装饰器 示例: 二、类装饰器 示例:

  • python3基础---详解装饰器

    1、装饰器原理 2、装饰器语法 3、装饰器执行的时间 装饰器在Python解释器执行的时候,就会进行自动装饰,并不...

  • 2019-05-26python装饰器到底是什么?

    装饰器例子 参考语法 装饰器是什么?个人理解,装饰器,是python中一种写法的定义。他仍然符合python的基本...

  • 2018-07-18

    Python装饰器 装饰,顾名思义,是用来打扮什么东西的。Python装饰...

网友评论

      本文标题:Python装饰器

      本文链接:https://www.haomeiwen.com/subject/lwtmbttx.html