zoukankan      html  css  js  c++  java
  • 8 python高阶函数、返回函数、装饰器

      1 ################################################################################
      2 ##------------- 高阶函数  ----------------------------------------------------
      3 
      4 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数。
      5 高阶函数:
      6     即是函数的形参,是用来接受函数的。这样的函数叫做高阶函数。
      7 
      8 >>> def now():
      9 ...     print('2015-3-25')
     10 ...
     11 >>> f = now
     12 >>> f()
     13 2015-3-25
     14 函数对象有一个__name__属性,可以拿到函数的名字:
     15 
     16 >>> now.__name__
     17 'now'
     18 >>> f.__name__
     19 'now'
     20 
     21 说明:
     22 既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
     23 
     24 例如:
     25 一个最简单的高阶函数:
     26 
     27 def add(x, y, f):
     28     return f(x) + f(y)
     29 
     30 
     31 ##--------------- 高阶函数之 map()和reduce()函数----------------------------------------------
     32 map说明:
     33     map()函数接收两个参数,一个是函数,一个是 Iterable
     34     map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。
     35 
     36 例如:
     37 def f(x):
     38     return x * x
     39 
     40 r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
     41 print list(r)
     42 
     43 
     44 reduce说明:
     45         reduce把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,
     46         reduce把结果继续和序列的下一个元素做累积计算,其效果就是。
     47 
     48 例如:
     49 from functools import reduce
     50 def add(x, y):
     51     return x + y
     52 
     53 print reduce(add, [1, 3, 5, 7, 9])
     54 
     55 
     56 ##---------------- 高阶函数之 sorted() 排序算法函数 ---------------------------------------------------、
     57 
     58 说明:
     59 但如果是字符串或者两个dict呢?直接比较数学上的大小是没有意义的,因此,比较的过程必须通过函数抽象出来。
     60 
     61 例如1:
     62     python内置的sorted()函数就可以对list进行排序:
     63 
     64 print sorted([36, 5, -12, 9, -21])
     65 结果:[-21, -12, 5, 9, 36]
     66 
     67 
     68 例如2:
     69     此外,sorted()函数也是一个高阶函数,它还可以接收一个key函数来实现自定义的排序,例如按绝对值大小排序:
     70     key指定的函数将作用于list的每一个元素上,
     71     并根据key函数返回的结果进行排序。对比原始的list和经过key=abs处理过的list:
     72 
     73 print sorted([36, 5, -12, 9, -21], key=abs)
     74 结果:[5, 9, -12, -21, 36]
     75 
     76 
     77 ##---------------- 高阶函数之 filter() 函数----------------------------------------------------
     78 
     79 filter说明:
     80 filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。
     81 
     82 例如:
     83 def is_odd(n):
     84     return n % 2 == 1
     85 
     86 print list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
     87 # 结果: [1, 5, 9, 15]
     88 
     89 
     90 ##-----------------返回函数 (函数作为返回值)------------------------------------------------
     91 
     92 返回函数说明:
     93     高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。
     94 
     95 
     96 我们来实现一个可变参数的求和。通常情况下,求和的函数是这样定义的:
     97 
     98 def calc_sum(*args):
     99     ax = 0
    100     for n in args:
    101         ax = ax + n
    102     return ax
    103 
    104 
    105 但是,如果不需要立刻求和,而是在后面的代码中,根据需要再计算怎么办?可以不返回求和的结果,而是返回求和的函数:
    106 
    107 def lazy_sum(*args):
    108     def sum():
    109         ax = 0
    110         for n in args:
    111             ax = ax + n
    112         return ax
    113     return sum
    114 当我们调用lazy_sum()时,返回的并不是求和结果,而是求和函数:
    115 
    116  f = lazy_sum(1, 3, 5, 7, 9)
    117  print f()                    --调用函数f时,才真正计算求和的结果:
    118 
    119 结果:25
    120 
    121 说明:
    122     在这个例子中,我们在函数lazy_sum中又定义了函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,
    123     当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。
    124 
    125 ##------------- 装饰器函数(即形参是函数的返回函数)  ----------------------------------------------------
    126 
    127 装饰器的定义
    128 本质是函数。(装饰其他函数) 它可以让其他函数在不需要做任何代码变动的前提下增加额外功能。
    129 
    130 装饰器的重要性
    131 比如:已经上线的生产环境上有100个函数,需要增加新功能,新增功能不能修改源代码,也不能修改原函数的,这个时候就用到了装饰器。
    132 
    133 装饰器经常有切面需求的场景,
    134     比如:插入日志,性能测试,事务处理,缓存,权限校验等场景。
    135     装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。 
    136     概括的讲,装饰的作用就是为已经存在的对象添加额外的功能。
    137 
    138 说明:
    139 现在,假设我们要增强now()函数的功能,
    140 比如,在函数调用前后自动打印日志,但又不希望修改now()函数的定义,
    141 这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。
    142 本质上,decorator就是一个返回函数的高阶函数。所以,我们要定义一个能打印日志的decorator,
    143 
    144 装饰器函数:
    145     其实本质就是一个返回函数,只不过是此返回函数本身又是高阶函数。
    146     即 即是高阶函数(参数是函数)又是返回函数(返回值是函数)
    147 
    148 装饰器函数的原理:
    149     就是利用返回函数的作用,将一个函数包在返回函数里面,
    150     1,第一次调用返回函数,并且将需要被装饰的函数传参进去
    151     2,第二次调用返回值,就是调用了内部函数,就是调用了被装饰过后的第一次传参进去的函数(在这次调用时可以加上其它功能的代码运行)
    152     
    153 ##装饰器的经典应用
    154 import os
    155 import sys
    156 import re
    157 import time
    158 
    159 # 这里的timer就是一个装饰器   ,
    160 #func形参就是用来接受需要被装饰的函数,
    161 #后面test1就是需要被装饰的函数,
    162 #装饰的效果就是在被装饰的函数运行前后加上了start_time和end_time
    163 def timer(func):
    164     def deco(*args, **kwargs):
    165         start_time = time.time()
    166         func(*args, **kwargs)
    167         end_time = time.time()
    168         print("the func [%s] run time is %s" %(func.__name__,end_time-start_time))
    169     return deco
    170 
    171 # 装饰器的调用,将函数返回值赋值给test1(注意:!! 装饰器,在装饰的时候就已经调用了第一次,即已经装饰好了,后面直接再第二次调用函数即可)
    172 # test1 = timer(test1)
    173 @timer  
    174 def test1():
    175     time.sleep(3)
    176     print("in the test1")
    177 
    178 
    179 ##test1函数调用(此时的test1已经不再是之前定义的,而是timer 装饰器返回的一个函数)
    180 test1()
    181 
    182 ########################装饰器之wraps###################################################################
    183 #coding=utf-8  
    184 # -*- coding=utf-8 -*-   
    185 from functools import wraps     
    186 def my_decorator(func):  
    187     #@wraps(func)  
    188     def wrapper(*args, **kwargs):  
    189         '''''decorator'''  
    190         print('Calling decorated function...')  
    191         return func(*args, **kwargs)  
    192     return wrapper    
    193  
    194 @my_decorator   
    195 def example():  
    196     """Docstring"""   
    197     print('Called example function')  
    198 print(example.__name__, example.__doc__)
    199 
    200 例如:
    201     以上代码,
    202     没有@wraps(func)此句时:
    203     >>('wrapper', 'decorator')
    204     有@wraps(func)时:
    205     >>('example', 'Docstring')
    206 
    207 说明:
    208     __name__   属性是类或函数的名字属性
    209     __doc__   属性,是类、函数、文件中特殊位置的字符串
    210     1. 一个文件任何一条可执行的代码之前  #模块的__doc__
    211 
    212     2. 一个类,在类定义语句后,任何可执行代码前  #类的__doc__
    213 
    214     3. 一个函数,在函数定义语句后,任何可执行代码前  #函数的__doc__
    215 
    216 作用:
    217 Python装饰器(decorator)在实现的时候,
    218 被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变),
    219 为了不影响,Python的functools包中提供了一个叫wraps的decorator来消除这样的副作用。
    220 写一个decorator的时候,最好在实现之前加上functools的wrap,它能保留原有函数的名称和docstring。
    221 
    222 
    223 
    224 ############### 基于python的-@property与@setter装饰器 ####################################
    225 此装饰器所添加的功能:
    226 property可以将方法转化成属性。
    227 所以一般用于类中,写在类中方法上面,(即此装饰器装饰了这个方法,后面调用这个方法就可以用属性的方式来调用方法)
    228 
    229 class People(object):  
    230     @property  
    231     def getAge(self):  
    232         return self.age  
    233     @age.setter  
    234     def setAge(self, age):  
    235         if age<0:  
    236             raise ValueError('age error!')  
    237         else:  
    238         self.age = age 
    239 
    240 在getter上加上property装饰器之后就可以直接以这种方式people.age获取age的值,settler的做法差不多只是装饰器的写法不一致而已将【变量名】
    241 .setter写在setter上面即可完成,从此设置age不用使用setter那么麻烦了,可以直接使用people.age=60这样的写法啦
  • 相关阅读:
    Django之POST GET与前后端交互
    Django中用户权限模块
    Django运算表达式与Q对象/F对象
    Django中Middleware中间件
    Form表单 JSON Content-type解析
    浅析ajax原理与用法
    浅析Django之session与cookie
    浅谈HTTP协议
    Django 项目搭建(ubuntu系统)
    h5 和之前版本的区别
  • 原文地址:https://www.cnblogs.com/2mei/p/9254089.html
Copyright © 2011-2022 走看看