Python核心编程笔记 - 第11章 函数式编程

来源:互联网 发布:淘宝卖家开店时间查询 编辑:程序博客网 时间:2024/06/05 16:03

lambda 函数

lambda函数的格式:

lambda [arg1[, arg2, ... argN]]: expression

示例代码:

my_add = lambda x, y: x+ yprint my_add(10, 20)  # 30my_tuple = lambda *num: numprint my_tuple(10, 20, 30, 'Hello')  # (10, 20, 30, 'Hello')

内建函数 filter(), map(), reduce()

built-in 函数 描述 filter(func, seq) 用bool函数func来遍历seq中的每个元素,返回一个使func为true的元素列表 map(func, seq1[, seq2…]]) 将函数func作用于给定序列s的每一个元素,并用一个列表作为返回值。若func为None,则返回一个含有多个元组的列表,而每个元组就是每个序列相同位置的元素的集合。 reduce(func, seq[, init]) 将二元函数作用于seq序列的元素,每次携带一对(先前的结果以及下一个序列元素),连续地将现有的结果和下一个值作用在获得的随后结果上,直到最后只有一个返回值。如果初始值init被给定,第一个比较就是init和第一个序列元素,而不是序列的头2个元素。

filter()的示例代码:

my_list = range(11)my_odd_list = filter(lambda x: x % 2 == 1, my_list)print my_odd_list  ## [1, 3, 5, 7, 9]

map()的示例代码:

>>> map(lambda x: x**2, range(6))[0, 1, 4, 9, 16, 25]>>>>>> map(lambda x, y: x + y, [1, 3, 5], [2, 4, 6])[3, 7, 11]>>>>>> map(lambda x, y: (x+y, x-y), [1, 3, 5], [2, 4, 6])[(3, -1), (7, -1), (11, -1)]

还有一个zip()函数,就是将所有列表中对应位置的元素组成一个元组,这多个元组形成一个新的列表,示例代码如下:

>>> zip([1, 3, 5], [2, 4, 6])[(1, 2), (3, 4), (5, 6)]>>>>>> zip([1, 3, 5], [2, 4, 6], [7, 8, 9])[(1, 2, 7), (3, 4, 8), (5, 6, 9)]

reduce()的示例代码:

>>> reduce(lambda x,y: x+y, range(101))5050

reduce()的原理就是:

def mimic_reduce(func, seq, init=None):    my_list = list(seq)    res = init if init is None else my_list.pop(0)    for item in my_list:        res = func(res, item)    return res

偏函数(partial)的应用

简单的示例代码:

from operator import add, mulfrom functools import partialadd100 = partial(add, 100)  # add100(x) == add(100, x)mul2 = partial(mul, 2)      # mul2(x) == mul(2, x)print add100(200) # 300print mul2(9)  # 18

又如:

>>> int('10010', base=2)18>>> BaseTwo = partial(int, base=2)>>> BaseTwo('10010')18

闭包 (closure)

在一个内部函数里,对在外部作用域(但不是全局作用域)的变量进行引用,那么这个内部函数就被认为是闭包(closure)。

简单的闭包示例代码:

# Note: This program does not work if change class Num to int. # This is because primitive type is passed by value rather than reference. class Num():    def __init__(self, val):        self.value = val    def __str__(self):        return str(self.value)def counter(num):    counting = num    def incr():        counting.value += 1        return counting    return incrc = counter(Num(100))print c()  # 101print c()  # 102print c()  # 103d = counter(Num(200))print d()  # 201print d()  # 202print c()  # 104

以下是一个演示闭包的有趣的例子:

from time import timedef logged(when):    def log(f, *args, **kargs):        print '''Called:function: %sargs: %rkargs: %r''' % (f, args, kargs)    def pre_logged(f):        def wrapper(*args, **kargs):            log(f, *args, **kargs)            return f(*args, **kargs)        return wrapper    def post_logged(f):        def wrapper(*args, **kargs):            now = time()            try:                return f(*args, **kargs)            finally:                log(f, *args, **kargs)                print "time delta: %s" % (time() - now)        return wrapper    try:         return {"pre": pre_logged, "post": post_logged}[when]    except KeyError, e:        raise ValueError(e), 'must be "pre" or "post"'@logged("post")def hello(name):    print "Hello, ", namehello("World")

执行结果为:

Hello,  WorldCalled:function: <function hello at 0x6ffffde6d70>args: ('World',)kargs: {}time delta: 0.0

生成器(Generator)

协同程序:
协同程序是可以运行的独立的函数调用,可以暂停或者挂起,并且从程序离开的地方继续或者重新开始。

挂起返回出中间值并多次继续的协同程序被称作生成器。

什么是Python式的生成器呢?从语法上讲,生成器是一个带yield语句的函数。一个函数或者子程序只返回一次,但是一个生成器能暂停执行并返回一个中间结果 – 即yield语句的功能 - 返回一个值给调用者并暂停执行。当生成器的next()方法被调用的时候,它会准确地从离开的地方继续。

当到达一个真正的返回或者函数结束没有更多的值返回时,一个StopIteration异常就会被抛出。

示例代码:

def SimpleGen():    yield 1    yield '2 - End'for eachItem in SimpleGe():    print eachItem# Will print:# 1# 2 - End

由于Python的for循环有next()调用和对StopIteration的处理,所以使用for循环而不是手动迭代一个生成器总是要简洁很多。

使用生成器最好的地方是当你正在迭代遍历一个巨大的数据集合。(笔者注: 可以节省大量的内存,即不用事先将整个数据集合装入内存)

在Python2.5中,一些新的特性被加到了生成器中。

  • 用户可以用send()将值送回生成器中;
  • 用户可以要求生成器退出(close());

示例代码:

def counter(start=0):    count = start    while True:        val = yield count        if val is not None:  # Note, when send() happens, here will be True            count = val        else:            count += 1count = counter(100)print count.next()print count.next()print count.send(200)print count.next()count.close()print count.next()

运行结果:

100101200201Traceback (most recent call last):  File "<stdin>", line 1, in <module>  File "./1.py", line 19, in <module>    print count.next()StopIteration
1 0
原创粉丝点击