# 函数式编程
## 装饰器 *有点面向切面的意思*
> http://python.jobbole.com/82112/
> 内置装饰器 有:静态方法staticmethod、类方法classmethod和类方法转换成属性访问property
def log(func):
def wrapper(*args, **kw):
print 'call %s():' % func.__name__
return func(*args, **kw)
return wrapper
@log
def action():
print '2013-12-25'
#把@log放到now()函数的定义处,相当于执行了语句 now = log(now)
> **上例** 每个动作都要记录日志;把动作函数传入log方法 返回一个闭包 后面调用的action实际就是wrapper
### 有参数的装饰器
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 '2013-12-25'
#把@log('execute')放到now()函数的定义处,相当于执行了语句 now = log('execute')(now)
### 注意 属性变化
> now.\_\_name\_\_ 已经变成了 wrapper
需要把 now的属性复制到 wrapper函数中 否则依赖函数属性(签名)的代码会出错
不需要编写wrapper.\_\_name\_\_ = func.\_\_name\_\_这样的代码,Python内置的functools.wraps就是干这个事的
wrapper函数上面 加上 @functools.wraps(func)
## 闭包
> **todo** 闭包的使用情景举例
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 调用函数f时,才真正计算求和的结果:
> 我们在函数lazy_sum中又定义了函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)
> 当我们调用lazy_sum()时,每次调用都会返回一个新的函数,即使传入相同的参数
def count():
fs = []
for i in range(1, 4):
def f():
return i*i
fs.append(f)
return fs
f1, f2, f3 = count()
f1() f2() f3() # 9 9 9
#原因就在于返回的函数引用了变量i,但它并非立刻执行。等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果为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
f1() f2() f3() # 1 4 9
## 偏函数
def int2(x, base=2):
return int(x, base)
int2 = functools.partial(int, base=2) # functools.partial就是帮助我们创建一个偏函数
int2('1000000') # 64
## 高阶函数
> 函数名也是变量、函数名也可以赋值给变量
> 函数名赋值常量以后 不能在调用
abs(-10) 绝对值
f = abs
f(-10)
abs = 10
abs(-10) # TypeError: 'int' object is not callable
#由于abs函数实际上是定义在import builtins模块中的,所以要让修改abs变量的指向在其它模块也生效,要用import builtins; builtins.abs = 10
> 函数可以作为参数
def add(x,y,f):
return f(x) + f(y)
add(-5,6,abs) # 11
## map reduce filter sorted函数
> map 对一个迭代对象元素使用f函数 并返回新的迭代对象
list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
> reduce这个函数必须接收两个参数,把结果继续和序列的下一个元素做累积计算
from functools import reduce
def add(x, y):
return x + y
reduce(add, [1, 3, 5, 7, 9])
> filter 传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素
list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])) # is_odd 只保留奇数
> sorted()函数就可以对list进行排序
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True)
## lambda x,y: x+y lambda [参数...] : 返回值