# python精简笔记(五)——函数式编程

Python对函数式编程提供部分支持。由于Python允许使用变量，因此，Python不是纯函数式编程语言。

# 返回函数

``````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
``````

``````>>> f1 = lazy_sum(1, 3, 5, 7, 9)
>>> f2 = lazy_sum(1, 3, 5, 7, 9)
>>> f1==f2
False
``````

`f1()``f2()`的调用结果互不影响。

# 闭包

``````
def count():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f)
return fs

f1, f2, f3 = count()

``````

``````>>> f1()
9
>>> f2()
9
>>> f3()
9
``````

``````def count():
def f(j):
def g():
return j*j
return g
fs = []
for i in range(1, 4):
fs.append(f(i)) # f(i)立刻被执行，因此i的当前值被传入f()
return fs
``````

# 匿名函数 lambda

``````def f(x):
return x * x

``````

``````>>> f = lambda x: x * x
>>> f
<function <lambda> at 0x101c6ef28>
>>> f(5)
25
``````

``````def build(x, y):
return lambda: x * x + y * y
``````

# 装饰器

``````>>> def now():
... print('2015-3-25')
...
>>> f = now
>>> f()
2015-3-25
``````

``````>>> now.__name__
'now'
>>> f.__name__
'now'
``````

`Decorator`就是一个返回函数的高阶函数。可以定义如下：

``````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()
call now():
2015-3-25
``````

`@log`放到`now()`函数的定义处，相当于执行了语句：

``````now = log(now)
``````

``````def log(text):
def decorator(func):
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
``````

``````@log('execute')
def now():
print('2015-3-25')
``````

``````now = log('execute')(now)
``````

Python内置的`functools.wraps` 可以解决这个问题，只需记住在定义`wrapper()`的前面加上`@functools.wraps(func)`即可。

``````import functools

def log(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
``````

# 偏函数

`int()`函数可以把字符串转换为整数，当仅传入字符串时，`int()`函数默认按十进制转换，如果传入base参数，就可以做N进制的转换：

``````>>> int('12345', base=8)
5349
>>> int('12345', 16)
74565

``````

``````>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85
``````

``````int2 = functools.partial(int, base=2)
int2('10010')
``````

``````kw = { 'base': 2 }
int('10010', **kw)
``````

``````max2 = functools.partial(max, 10)
``````

``````max2(5, 6, 7)
``````

``````args = (10, 5, 6, 7)
max(*args)
``````
python手记