Size: 5509
Comment:
|
← Revision 30 as of 2009-12-25 07:15:25 ⇥
Size: 9032
Comment: converted to 1.6 markup
|
Deletions are marked like this. | Additions are marked like this. |
Line 8: | Line 8: |
-- hoxide [[[DateTime(2004-09-08T23:06:48Z)]]] [[TableOfContents]] |
-- hoxide [<<DateTime(2004-09-08T23:06:48Z)>>] <<TableOfContents>> |
Line 20: | Line 20: |
''简述'' | |
Line 39: | Line 38: |
例如: | 例如: |
Line 44: | Line 43: |
就生成了一个函数 λ(x) = x+1. 具有可以在python的解释器中试试: |
就生成了一个函数 λ(x) = x+1. 具有可以在python的解释器中试试: |
Line 57: | Line 56: |
lambda的具体语法是: lambda [parameter_list]: expression parameter_list 是参数表, expression 是后面跟的表达式, lambda本身是个运算符, 作用在这两个元素上产生一个匿名函数, 类似于以下函数定义: |
lambda的具体语法是: lambda [parameter_list]: expression parameter_list 是参数表, expression 是后面跟的表达式, lambda本身是个运算符, 作用在这两个元素上产生一个匿名函数, 类似于以下函数定义: |
Line 69: | Line 68: |
expression 是一个合法的python表达式, 显然 expression 中的变量量除了在 parameter_list 中的外必须是已知的. 注意experssion中是不能用print语句的, 要想产生输出的话可以用sys.stdout.write()等函数. 下面会不断给出 lambda 的例子 == 辅助算符 == 所谓的辅助算符在python中其实是一组很有用的函数. |
expression 是一个合法的python表达式, 显然 expression 中的变量量除了在 parameter_list 中的外必须是已知的. 注意experssion中是不能用print语句的, 要想产生输出的话可以用sys.stdout.write()等函数. 下面会不断给出 lambda 的例子 == 高阶函数 == 所谓的高阶函数其实是一组以函数为参量的函数. 下面介绍 Python 中的具体形式. |
Line 93: | Line 92: |
例如: | 例如: |
Line 103: | Line 102: |
另一种多参数调用的方法是组合列表: | 另一种多参数调用的方法是组合列表(这也是我本人最喜欢用的方法): |
Line 106: | Line 105: |
这种方法实质还是单参数调用(这个不一定要完全理解). 例如: |
这种方法实质还是单参数调用(这个不一定要完全理解). 例如: |
Line 116: | Line 115: |
如果map 的第一个参数, 即function等于None, 则默认为恒等变换. 例: |
如果map 的第一个参数, 即function等于None, 则默认为恒等变换. 例: |
Line 125: | Line 124: |
== reduce == | === reduce === |
Line 128: | Line 127: |
Apply function of two arguments cumulatively to the items of sequence, from left to right, so as to reduce the sequence to a single value. For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates ((((1+2)+3)+4)+5). The left argument, x, is the accumulated value and the right argument, y, is the update value from the sequence. If the optional initializer is present, it is placed before the items of the sequence in the calculation, and serves as a default when the sequence is empty. If initializer is not given and sequence contains only one item, the first item is returned. == filter == |
将函数function从左到右作用在序列的每个元素上, 函数function为二元函数, 第一个变量为上次计算所得结果,第二个变量为列表元素. 具体得: {{{ #!python >>> reduce(lambda x,y: x+y , [1,2,3,4,5]) # 相当于 ((((1+2)+3)+4)+5) 15 }}} 整个计算过程就像列表在不断缩减一样. initializer为初值. 例如: {{{ >>> reduce(lambda x,y: x+y , [1,2,3,4,5], 10) # 相当于(((((10+1)+2)+3)+4)+5) 25 }}} === filter === |
Line 133: | Line 148: |
Construct a list from those elements of list for which function returns true. list may be either a sequence, a container which supports iteration, or an iterator, If list is a string or a tuple, the result also has that type; otherwise it is always a list. If function is None, the identity function is assumed, that is, all elements of list that are false (zero or empty) are removed. Note that filter(function, list) is equivalent to [item for item in list if function(item)] if function is not None and [item for item in list if item] if function is None. |
filter 过滤器. 从list的元素中构造一个列表, 这个列表的元素依次是list中使function为真的元素. list可以是任意序列, 如列表(List)和元组(Tuple)等, 或支出迭代子的容器, 或者迭代子(有关容器,迭代子等概念将在下面介绍,) 例子: {{{ #!python >>> filter(lambda x: x>5 , [10,1,5,6,7]) # 将列表中小于5的元素滤去. [10, 6, 7] }}} 和map一样, 若function是None , 则代为恒等函数, 这样将滤去所有取值为false的元素(包括0和None). = 列表运算 = 目前 Guido 对Python的函数式编程很不满意, 它计划在Python3000中去除这写函数, 取而代之的是列表运算. 这些方法在当前的Python版本中也是可用的. 基本形式是 [expression for expression_list in testlist ] 和前面一样 testlist 是一个序列或者迭代子 expression是一个表达式 expression_list 是这个表达式中的参量列表(实质上是解开一个元组). 例如: {{{ #!python >>> [ x+y for x,y in [(1,2), (2,3), (4,5)]] [3, 5, 9] >>> [ item[0]+item[1] for item in [(1,2), (2,3), (4,5)]] # 和前面的等价 [3, 5, 9] }}} for 语句可以套用: {{{ #!python >>> [ (i,j) for i in range(5) for j in range(3)] # 这个例子可以看出靠近expression的循环是内层循环 [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2), (3, 0), (3, 1), (3, 2), (4, 0), (4, 1), (4, 2)] }}} for后面还可以跟if语句, 这样相当于一个增强的 filter 例如: {{{ #!python >>> [ i for i in range(10) if i%2==0] # 选出所有偶数 [0, 2, 4, 6, 8] }}} 同样 if 也可以嵌套, 并可以与for混合嵌套 (但是, 显然过多的嵌套容易使语句变得晦涩难懂) : {{{ #!python >>> [ (i,j) for i in range(10) if i%2==0 for j in range(10) if j%3 == 0] [(0, 0), (0, 3), (0, 6), (0, 9), (2, 0), (2, 3), (2, 6), (2, 9), (4, 0), (4, 3), (4, 6), (4, 9), (6, 0), (6, 3), (6, 6), (6, 9), (8, 0), (8, 3), (8, 6), (8, 9)] }}} |
Line 140: | Line 208: |
前面很粗浅得讲了一下Python中函数编程的最基本内容, 下面将列出一些常用的函数编程方法, 这些方法可以大大简化你的代码. |
|
Line 142: | Line 212: |
编程的东西如果理解原来, 不管用那种方法写程序其实都是一样的, 函数编程只是一种方法, 用好了可以简化程序. === 算24点的程序 === 这只是一个用了点函数编程方法随手写的程序, 1年前的东西, 不是算24点的最好方法, 拿到这里, 只是展示一下函数编程的用法. {{{ #!python funs = [ lambda x, item: (x+item[0], str(x)+'+('+item[1]+')' ), lambda x, item: (x-item[0], str(x)+'-('+item[1]+')' ), lambda x, item: (item[0]-x, '('+item[1]+')-'+str(x) ), lambda x, item: (x*item[0], str(x)+'*('+item[1]+')' ), lambda x, item: (item[0]==0 and (0,'ZZZ')) or \ (x/item[0], str(x)+'/('+item[1]+')' ), lambda x, item: (x==0 and (0,'ZZZ')) or \ (item[0]/x, '('+item[1]+')/'+str(x) ) ] def con(num): l = len(num) p = list() if l==1: return {num[0]:str(num[0])} for i in range(l): for f in funs: p += map(lambda item: f(num[i],item), con(num[:i]+num[i+1:]).items() ) return dict(p) print con(map(float,[1,5,6,7])).get(21.0,0) }}} |
|
Line 143: | Line 258: |
待补齐 | 函数编程最明显的缺陷是易用性不够, 对于大多数初学者来说, 函数编程是不容易理解的, 写出正确的函数式程序是有困难的. 同样函数式编程的形式中含有很多的嵌套, 这也使程序看起来很晦涩, 这正是 Guido 计划取消Python中函数式编程特性的原因之一. |
Line 149: | Line 266: |
* ["FP编程的一点资料"] 有了系统的转载, 先并人(入) ["FLOSS"] -- Py Tips 了是也乎! -- Zoomq | * '''[[self:FunctionProgramAbt|"FP编程的一点资料"]]''' 有了系统的转载, 先并人(入) [[FLOSS]] -- Py Tips 了是也乎! -- Zoomq |
函数编程, 任何人可以以任何方式随意转载. 清剿太监贴~~ , 把没完成的东西完成之
-- hoxide [2004-09-08 23:06:48]
Contents
前言
本文的写作计划源于2004年9月 GreyRoar 的提议, 可惜真正动手却推到了现在, 在近一年的时间里, python的函数编程也发生了一些改变, python3000计划和最近的已经出现的"匿名块"等都使得python在这个方面的发展充满着不确定因素, 本文只讨论目前已知的能用的功能, 不保证满足将来可能发生的变化. 另外在一切开始前, 记住Python和数学里一样记号只是记号.
函数式编程的概念
- 函数编程源自 Lisp 等高阶语言, 他们以λ演算为基础. 所谓λ演算其实指基于算子λ的一个演算体系. 他的特殊性在于, 存在一个算子 λ (λ只是记号, 没有更多含义), 他的作用是将运算式子变成函数 . 例如: λx: x+1 就将 x+1这个运算式子, 变成了关于x的一个函数, 他的值是x+1. 光有λ算子构成不了完整的λ运算体系, 还需要一些辅助算子, 但是λ演算体系的基础就是这个算子. 要完全了解这个体系则需要一环扣一环的定义和定理, 太复杂这里不再详述(书丢学校了, 回校有时间补齐 :P ).
python中的函数编程
lambda
- 和数学中的 λ 一样, python的函数编程体系中有一个 lambda 语句, 用来生成函数, 一般这样的函数称为匿名函数. 例如:
1 lambda x: x+1
- 就生成了一个函数 λ(x) = x+1. 具有可以在python的解释器中试试:
- lambda的具体语法是: lambda [parameter_list]: expression parameter_list 是参数表, expression 是后面跟的表达式, lambda本身是个运算符, 作用在这两个元素上产生一个匿名函数, 类似于以下函数定义:
- expression 是一个合法的python表达式, 显然 expression 中的变量量除了在 parameter_list 中的外必须是已知的. 注意experssion中是不能用print语句的, 要想产生输出的话可以用sys.stdout.write()等函数. 下面会不断给出 lambda 的例子
高阶函数
- 所谓的高阶函数其实是一组以函数为参量的函数. 下面介绍 Python 中的具体形式.
map
- map是最基本的函数, 搞懂了map其他函数就很容易搞懂. map 的定义: map( function, list, ...) 将函数function作用到 list 的每个元素上, 将结果组成一个列表返回. 如果参数列表有多个, 函数应该是有多参数的, 每个分量取各列表上的对应值, 如果有列表比其他列表短, 不足部分当作 None . 这里list可以是任意序列(sequence), 例如列表(list) , 元组(tuple)等. 例如:
- 另一种多参数调用的方法是组合列表(这也是我本人最喜欢用的方法): map(lambda (arg1, ..., argn): expression, multiple_list), multiple_list 是一个列表, 他的元素还是一个列表, 即参数列表. 这种方法实质还是单参数调用(这个不一定要完全理解). 例如:
- 如果map 的第一个参数, 即function等于None, 则默认为恒等变换. 例:
reduce
reduce( function, sequence[, initializer])
将函数function从左到右作用在序列的每个元素上, 函数function为二元函数, 第一个变量为上次计算所得结果,第二个变量为列表元素. 具体得:
整个计算过程就像列表在不断缩减一样.
initializer为初值. 例如:
>>> reduce(lambda x,y: x+y , [1,2,3,4,5], 10) # 相当于(((((10+1)+2)+3)+4)+5) 25
filter
filter( function, list)
filter 过滤器.
从list的元素中构造一个列表, 这个列表的元素依次是list中使function为真的元素. list可以是任意序列, 如列表(List)和元组(Tuple)等, 或支出迭代子的容器, 或者迭代子(有关容器,迭代子等概念将在下面介绍,)
例子:
和map一样, 若function是None , 则代为恒等函数, 这样将滤去所有取值为false的元素(包括0和None).
列表运算
- 目前 Guido 对Python的函数式编程很不满意, 它计划在Python3000中去除这写函数, 取而代之的是列表运算. 这些方法在当前的Python版本中也是可用的.
基本形式是 [expression for expression_list in testlist ]
和前面一样 testlist 是一个序列或者迭代子 expression是一个表达式 expression_list 是这个表达式中的参量列表(实质上是解开一个元组). 例如:
for 语句可以套用:
for后面还可以跟if语句, 这样相当于一个增强的 filter
例如:
同样 if 也可以嵌套, 并可以与for混合嵌套 (但是, 显然过多的嵌套容易使语句变得晦涩难懂) :
基本方法综述
前面很粗浅得讲了一下Python中函数编程的最基本内容, 下面将列出一些常用的函数编程方法, 这些方法可以大大简化你的代码.
应用实例
编程的东西如果理解原来, 不管用那种方法写程序其实都是一样的, 函数编程只是一种方法, 用好了可以简化程序.
算24点的程序
这只是一个用了点函数编程方法随手写的程序, 1年前的东西, 不是算24点的最好方法, 拿到这里, 只是展示一下函数编程的用法.
1 funs = [ lambda x, item: (x+item[0],
2 str(x)+'+('+item[1]+')'
3 ),
4 lambda x, item: (x-item[0],
5 str(x)+'-('+item[1]+')'
6 ),
7 lambda x, item: (item[0]-x,
8 '('+item[1]+')-'+str(x)
9 ),
10 lambda x, item: (x*item[0],
11 str(x)+'*('+item[1]+')'
12 ),
13 lambda x, item: (item[0]==0 and (0,'ZZZ')) or \
14 (x/item[0],
15 str(x)+'/('+item[1]+')'
16 ),
17 lambda x, item: (x==0 and (0,'ZZZ')) or \
18 (item[0]/x,
19 '('+item[1]+')/'+str(x)
20 )
21 ]
22
23 def con(num):
24 l = len(num)
25 p = list()
26 if l==1: return {num[0]:str(num[0])}
27 for i in range(l):
28 for f in funs:
29 p += map(lambda item: f(num[i],item),
30 con(num[:i]+num[i+1:]).items()
31 )
32 return dict(p)
33
34 print con(map(float,[1,5,6,7])).get(21.0,0)
函数编程的缺陷
- 函数编程最明显的缺陷是易用性不够, 对于大多数初学者来说, 函数编程是不容易理解的, 写出正确的函数式程序是有困难的. 同样函数式编程的形式中含有很多的嵌套, 这也使程序看起来很晦涩, 这正是 Guido 计划取消Python中函数式编程特性的原因之一.
例子
交流
已经开始了?强烈支持呀,呵呵——GreyRoar
"FP编程的一点资料" 有了系统的转载, 先并人(入) FLOSS -- Py Tips 了是也乎! -- Zoomq