ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 函数式编程 ## 装饰器 *有点面向切面的意思* > 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 [参数...] : 返回值