今天看了函数式编程的内容,需要记录一下。
高阶函数
map/reduce
- map()函数
它接受两个参数,一个函数,一个Iterable,这个函数会作用于Iterable的每个元素,并把结果作为Iterator返回。
比如:
>>> def f(x):
... return x * x
...
>>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> list(r)
[1, 4, 9, 16, 25, 36, 49, 64, 81]
可见最后的结果是list中的每个元素都进行平方运算最后生成一个Iterator,然后用list方法进行输出。
- reduce()函数
它接受两个参数,一个函数,一个序列,用于把结果继续和序列的下个元素做累积计算。
比如:
>>> from functools import reduce
>>> def fn(x, y):
... return x * 10 + y
...
>>> reduce(fn, [1, 3, 5, 7, 9])
13579
list的前面两个元素做出的结果继续与后面的元素进行运算,以此类推。
filter
它也接受一个函数和一个序列作为参数,然后把传入的函数作用于序列中的每个元素,再根据返回的是True还是False决定保留或者删去元素。
比如:
>>> def is_odd(n):
... return n % 2 == 0
>>> list(filter(is_odd,[2,3,4,5,7,9,10]))
[2, 4, 10]
这个函数就可以保留偶数。
sorted
一般的排序用法。
>>> sorted([36, 5, -12, 9, -21])
[-21, -12, 5, 9, 36]
或者
>>> sorted([36, 5, -12, 9, -21], key=abs)
[5, 9, -12, -21, 36]
可以用key来指定排序的关键字。
当需要反向排序的时候可以这样:
sorted([-21, -12, 5, 9, 36],reverse=True)
[36, 9, 5, -12, -21]
加上reverse方法即可。
返回函数
- 函数可以当做结果值返回。
比如这个求和函数:
def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum
>>> f = lazy_sum(1, 3, 5, 7, 9)
>>> f
<function lazy_sum.<locals>.sum at 0x101c6ed90>
我们发现调用后返回的是一个函数而不是值,之后再次进行调用才可以。
>>> f()
25
当程序修改后才回返回计算的值:
def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum()
>>> f = lazy_sum(1, 3, 5, 7, 9)
>>> f
25
- 闭包
这样两个函数:
def count():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f())
return fs
f1, f2, f3 = count()
print(f1,f2,f3)
输出1 4 9
def count():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f)
return fs
f1, f2, f3 = count()
print(f1(),f2(),f3())
输出9 9 9
差别在哪里?
前者加入fs这个list的其实是经过计算后的值,也就是1、4、9。那么count()调用后就已经进行了运算,所以f1、f2、f3就分别对应的是list的三个值。
后者加入list的其实是三个函数,都是计算i*i的函数,也就是f1、f2、f3这三个元素。只有最后调用的时候才产生结果,那么调用的时候i已经是3了,所以结果相同了都是9。
匿名函数
匿名函数用法:
>>> list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
[1, 4, 9, 16, 25, 36, 49, 64, 81]
lambda x: x * x就是匿名函数。
装饰器
在代码运行期间动态增加功能的方式,称为“装饰器”。
- 函数的名字
函数对象有个name属性,可以拿到函数的名字,比如:
>>> int.__name__
'int'
- 要增强某个函数的功能,希望在调用前后打印日志。
比如:
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
利用@语法:
@log
def now():
print('2015-3-25')
调用now()函数:
>>> now()
call now():
2015-3-25
发现进行了日志输出。
偏函数
普通情况下,int会把字符串转换为整数,比如:
>>> int('12345')
12345
但是int()函数还提供额外的base参数,比如:
>>> int('12345', base=8)
5349
>>> int('12345', 16)
74565
利用偏函数:
>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85
这样重新定义后的int2函数就可以把二进制字符串转化为十进制数了。
网友评论