您的位置:首页 > 编程语言 > Python开发

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

2015-10-03 15:03 761 查看

lambda 函数

lambda函数的格式:

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


示例代码:

my_add = lambda x, y: x+ y
print my_add(10, 20)  # 30

my_tuple = lambda *num: num
print 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, mul
from functools import partial

add100 = partial(add, 100)  # add100(x) == add(100, x)
mul2 = partial(mul, 2)      # mul2(x) == mul(2, x)

print add100(200) # 300
print 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 incr

c = counter(Num(100))
print c()  # 101
print c()  # 102
print c()  # 103

d = counter(Num(200))
print d()  # 201
print d()  # 202
print c()  # 104


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

from time import time

def logged(when):
def log(f, *args, **kargs):
print '''Called:
function: %s
args: %r
kargs: %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, ", name

hello("World")


执行结果为:

Hello,  World
Called:
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 += 1

count = counter(100)
print count.next()
print count.next()

print count.send(200)
print count.next()
count.close()
print count.next()


运行结果:

100
101
200
201
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "./1.py", line 19, in <module>
print count.next()
StopIteration
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: