zoukankan      html  css  js  c++  java
  • Python【第四课】 装饰器

    本篇内容

    1. 什么是装饰器

    2. 装饰器需要遵循的原则

    3. 实现装饰器的知识储备

    4. 高阶函数

    5. 函数嵌套

    6. 闭包函数

    7. 无参函数

    8. 装饰器示例

    1.什么是装饰器

    器即函数

    装饰即修饰,意指为其他函数添加新功能

    装饰器定义:本质就是函数,功能是为其他函数添加新功能

    2.装饰器需要遵循的原则

    1.不修改被装饰函数的源代码(开放封闭原则)

    2.为被装饰函数添加新功能后,不修改被修饰函数的调用方式

    3.实现装饰器的知识储备

    装饰器=高阶函数+函数嵌套+闭包

    4.高阶函数

    高阶函数定义:
    1.函数接收的参数是一个函数名

    2.函数的返回值是一个函数名

    3.满足上述条件任意一个,都可称之为高阶函数

    # 接收的参数是一个函数名
    def count(func,num): num=func(num) print(num) count(abs,-10) # 输出 # 10
    # 返回值是一个函数
    def count():
        print('输出数字的绝对值方法:')
        return abs
    
    put=count()
    print(put(-10))
    
    # 输出
    # 输出数字的绝对值方法:
    # 10
    

    高阶函数总结
    1.函数接收的参数是一个函数名
      作用:在不修改函数源代码的前提下,为函数添加新功能,
      不足:会改变函数的调用方式
    2.函数的返回值是一个函数名
      作用:不修改函数的调用方式
      不足:不能添加新功能

    5.函数嵌套

    之前写过,去看看吧,我觉得写得还挺好的。

    函数基础:

    http://www.cnblogs.com/40kuai/articles/6374356.html

    6.闭包函数

    闭包是由函数及其相关的引用环境组合而成的实体(即:闭包=函数+引用环境)(想想Erlang的外层函数传入一个参数a, 内层函数依旧传入一个参数b, 内层函数使用a和b, 最后返回内层函数

    函数是什么
    地球人都知道:函数只是一段可执行代码,编译后就“固化”了,每个函数在内存中只有一份实例,得到函数的入口点便可以执行函数了。在函数式编程语言中,函 数是一等公民(First class value:第一类对象,我们不需要像命令式语言中那样借助函数指针,委托操作函数),函数可以作为另一个函数的参数或返回值,可以赋给一个变量。函数可 以嵌套定义,即在一个函数内部可以定义另一个函数,有了嵌套函数这种结构,便会产生闭包问题。如:

    >>> def ExFunc(n):
         sum=n
         def InsFunc():
                 return sum+1
         return InsFunc
    
    >>> myFunc=ExFunc(10)
    >>> myFunc()
    11
    >>> myAnotherFunc=ExFunc(20)
    >>> myAnotherFunc()
    21
    >>> myFunc()
    11
    >>> myAnotherFunc()
    21
    >>>
    

    在这段程序中,函数InsFunc是函数ExFunc的内嵌函数,并且是ExFunc函数的返回值。我们注意到一个问题:内嵌函数InsFunc中 引用到外层函数中的局部变量sum,IronPython会这么处理这个问题呢?先让我们来看看这段代码的运行结果。当我们调用分别由不同的参数调用 ExFunc函数得到的函数时(myFunc(),myAnotherFunc()),得到的结果是隔离的,也就是说每次调用ExFunc函数后都将生成并保存一个新的局部变量sum。其实这里ExFunc函数返回的就是闭包。

    引用环境
    按照命令式语言的规则,ExFunc函数只是返回了内嵌函数InsFunc的地址,在执行InsFunc函数时将会由于在其作用域内找不到sum变量而出 错。而在函数式语言中,当内嵌函数体内引用到体外的变量时,将会把定义时涉及到的引用环境和函数体打包成一个整体(闭包)返回。现在给出引用环境的定义就 容易理解了:引用环境是指在程序执行中的某个点所有处于活跃状态的约束(一个变量的名字和其所代表的对象之间的联系)所组成的集合。闭包的使用和正常的函 数调用没有区别。

    由于闭包把函数和运行时的引用环境打包成为一个新的整体,所以就解决了函数编程中的嵌套所引发的问题。如上述代码段中,当每次调用ExFunc函数 时都将返回一个新的闭包实例,这些实例之间是隔离的,分别包含调用时不同的引用环境现场。不同于函数,闭包在运行时可以有多个实例,不同的引用环境和相同 的函数组合可以产生不同的实例。

    6.1 闭包函数定义

    python中的闭包从表现形式上定义(解释)为:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure).

    >>>def addx(x):  
    >>>    def adder(y): return x + y  
    >>>    return adder  
    >>> c =  addx(8)  
    >>> type(c)  
    <type 'function'>  
    >>> c.__name__  
    'adder'  
    >>> c(10)  
    18  
    

    结合这段简单的代码和定义来说明闭包:
    如果在一个内部函数里:adder(y)就是这个内部函数,
    对在外部作用域(但不是在全局作用域)的变量进行引用:x就是被引用的变量,x在外部作用域addx里面,但不在全局作用域里,
    则这个内部函数adder就是一个闭包。  

    6.2 闭包函数的注意事项

    1.闭包中是不能修改外部作用域的局部变量的

    >>> def foo():  
    ...     m = 0  
    ...     def foo1():  
    ...         m = 1  
    ...         print m  
    ...  
    ...     print m  
    ...     foo1()  
    ...     print m  
    ...  
    >>> foo()  
    0  
    1  
    0  
    # 从执行结果可以看出,虽然在闭包里面也定义了一个变量m,但是其不会改变外部函数中的局部变量m。

    2.以下这段代码是在python中使用闭包时一段经典的错误代码

    def foo():  
        a = 1  
        def bar():  
            a = a + 1  
            return a  
        return bar  
    

    这段程序的本意是要通过在每次调用闭包函数时都对变量a进行递增的操作。但在实际使用时没有把参数传给闭包函数。

    其他详细见:http://www.cnblogs.com/JohnABC/p/4076855.html

    7.无参函数

    无参装饰器=高级函数+函数嵌套

    无参装饰器=高级函数+函数嵌套

    基本框架

    1 #这就是一个实现一个装饰器最基本的架子
    2 def timer(func):
    3     def wrapper():
    4         func()
    5     return wrapper

    加上参数

    1 def timer(func):
    2     def wrapper(*args,**kwargs):
    3         func(*args,**kwargs)
    4     return wrapper

    加上功能

    import time
    def timer(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            func(*args,**kwargs)
            stop_time=time.time()
            print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
        return wrapper

    加上返回值

    import time
    def timer(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            res=func(*args,**kwargs)
            stop_time=time.time()
            print('函数[%s],运行时间是[%s]' %(func,stop_time-start_time))
            return res
        return wrapper

    使用装饰器

    def cal(array):
        res=0
        for i in array:
            res+=i
        return res
    
    cal=timer(cal)
    cal(range(10))

    语法糖@

    @timer  #@timer就等同于cal=timer(cal)
    def cal(array):
        res=0
        for i in array:
            res+=i
        return res
    
    cal(range(10))
    

    小知识点:

    # import functools
    # @functools.wraps(func)
    # 被装饰器调用过的函数帮助信息显示为装饰器的帮助信息
    # 调入functools模块可以解决该问题
    

    8.装饰器示例

    无参装饰器
    带参装饰器

    抄袭地址:http://www.cnblogs.com/linhaifeng/articles/6140395.html

    最新内容可以看我的blog: 40kuai
  • 相关阅读:
    jquery点击添加样式,再点击取出样式
    mongodb固定集合,建立管理员安全验证
    mongodb账号安全操作
    关于新闻,在线编辑器建表时此字段一定要为text
    创建外键表时同一个数据库中外键的名字不能用同一个
    a标签鼠标经过,字颜色和下划线的颜色都变红
    zend 快捷键
    mongodb 的安装和使用
    pdo文字水印类,验证码类,缩略图类,logo类
    erlang通讯解析浮点数的一些问题
  • 原文地址:https://www.cnblogs.com/40kuai/p/6434126.html
Copyright © 2011-2022 走看看