在介绍函数式编程之前,先介绍几个概念性的东西。

什么是函数式编程?

函数式编程的特点:

1.把计算视为函数而非指令;

2.纯函数式编程:不需要变量,没有副作用,测试简单;

3.支持高阶函数,代码简洁。

什么是高阶函数?

能接收函数做参数的函数,称为高阶函数。

高阶函数的特点:

1.变量可以指向函数

2.函数的参数可以接收变量

3.一个函数可以接收另一个函数作为参数

Python支持的函数式编程?

1.不是纯函数式编程:允许有变量

2.支持高阶函数:函数也可以作为变量传入

3.支持闭包:有了闭包就能返回函数

4.有限度的支持匿名函数

关于匿名函数和闭包的介绍,后面会一一介绍,暂时不在这里详细介绍。

高阶函数-把函数作为参数

>>> def fn(x,y,f):
... return f(x)+f(y)
...
>>> import math
>>> fn(4,16,math.sqrt)
6.0

python内置的几个常用的高阶函数

map():接收一个函数f和一个list对象,函数f作用于list对象的每一个元素,并返回一个新的list对象。

>>> def fn(x):
... return x*x;
...
>>> print map(fn,range(1,11))
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

reduce():也是接收函数f和一个list对象,但是接收函数f必须传入两个参数,然后对lsit中的每一个元素反复调用函数f,并返回最终结果值。

>>> def prod(x,y):
... return x*y
...
>>> print reduce(prod,range(1,6))
120 //1 *2*3*4*5

filter():接收函数f和一个list对象,函数f的作用是对每一个list对象的元素进行判断,返回true 和false。filter()根据判断结果自动过滤掉不符合的元素,返回符合条件的元素组成的新list。

>>> def is_even_number(x):
... return x%2==0
...
>>> filter(is_even_number,range(1,11))
[2, 4, 6, 8, 10]

上面针对高阶函数讲解,大家应该了解了函数是可以作为参数的,那么既然函数可以做参数,那么也可以返回函数。

返回函数

>>> def f():
... print 'call f()....'
... //定义函数g:
... def g():
... print 'call g()....'
//返回函数g:
... return g
...
>>> x = f() //调用f()
call f()....
>>> x
<function g at 0x7f62fab01c80>
>>> x() //调用x()就是执行g()函数定义的代码
call g()....

举个例子:编写一个函数,接收一个list,返回一个函数,返回函数可以计算参数的乘积。

>>> def fn(x,y):
... return x*y;
...
>>> def calc_prod(lst):
... def my_calc():
... return reduce(fn,lst)
... return my_calc
...
>>> f = calc_prod(range(1,5))
>>> print f()
24

闭包

内层函数引用外层函数的变量,然后返回内层函数的情况,称为闭包。

闭包的特点:返回的函数引用了外层函数的局部变量。所以,要正确使用闭包,就能确保引用的局部变量在函数返回后不能改变。举例说明:

//希望一次返回3个函数,分别计算1x1,2x2,3x3
>>> def count():
... lst = []
... for i in range(1,4):
... def f():
... return i*i
... lst.append(f)
... return lst
...
>>> f1,f2,f3 = count()
>>> f1()
9
>>> f2()
9
>>> f3()
9

得到的结果并不是我们预期的1,4,9.

lst.append(f),只是将每一个f()的引用保存进了list,并没有进行对于i的计算,所以导致最后在运行了f(1)之后,i已经变为了3.

因此,返回函数不要引用任何循环变量,或者后续会发生变化的变量

那么怎么改写上述的代码,得到想要的1,4,9.值。

方法一:

>>> def count():
... lst = []
... for i in range(1,4):
... def f():
... return i*i
... lst.append(f()) //很大的不同,f 变为了f(),这一步的时候已经进行了i*i的运算
... return lst
...
>>> f1,f2,f3 = count()
>>> print f1,f2,f3
1 4 9

方法二:

>>> def count():
... lst = []
... for i in range(1,4):
... def f(m=i)://传入参数
... return m*m
... lst.append(f)
... return lst
...
>>> f1,f2,f3 = count()
>>> print f1(),f2(),f3()
1 4 9

问题的产生是因为函数只在执行时才去获取外层参数i,若函数定义时可以获取到i,问题便可解决。而默认参数正好可以完成定义时获取i值且运行函数时无需参数输入的功能,所以在函数f()定义中改为f(m = i),函数f返回值改为m*m即可.

匿名函数

关键字 lambda表示匿名函数,冒号前面的x表示函数参数。

匿名函数有个限制,就是只能有一个表达式,不能写return,返回值就直接写表达式的结果。

例子一:

>>> map(lambda x:x*x,range(1,5))
[1, 4, 9, 16]

lambda x:x*x,可以看做是

>>> def f(x):
... return x*x

例子二:

>>> myabs = lambda x:-x if x<0 else x
>>> myabs(-1)
1
>>> myabs(2)
2

lambda x:-x if x<0 else x可以看做是

>>> def f(x):
... x = -x
... if x<0:
... return -x
... else:
... return x

小结:这一节主要讲解python函数式编程概念及其python高阶函数的定义及其使用。

python学习第十一天 -- 函数式编程的更多相关文章

  1. Python学习总结之五 -- 入门函数式编程

    函数式编程 最近对Python的学习有些怠慢,最近的学习态度和学习效率确实很不好,目前这种病况正在好转. 今天,我把之前学过的Python中函数式编程简单总结一下,分享给大家,也欢迎并感谢大家提出意见 ...

  2. Python学习笔记二:函数式编程

    1:Python中,内置函数名相当于一个变量,指向内置函数.所以可以通过函数名调用相应函数,也可以给函数名赋值,改变它的内容,如:可以把另一个函数变量赋值给它,那它就指向了所赋值的函数了. 2:高级函 ...

  3. Python学习札记(二十) 函数式编程1 介绍 高阶函数介绍

    参考: 函数式编程 高阶函数 Note A.函数式编程(Functional Programming)介绍 1.函数是Python内建支持的一种封装,我们通过一层一层的函数调用把复杂任务分解成简单的任 ...

  4. Python学习一(面向对象和函数式编程)

    学习了一周的Python,虽然一本书还没看完但是也收获颇多,作为一个老码农竟然想起了曾经荒废好久的园子,写点东西当做是学习笔记吧 对Python的语法看的七七八八了,比较让我关注的还是他编程的思想,那 ...

  5. Python学习札记(二十三) 函数式编程4 sorted

    参考:sorted NOTE 1.sorted,快速排序,时间复杂度O(nlogn)渐进最优. #!/usr/bin/env python3 L = [] for i in range(10): L. ...

  6. Python学习札记(二十七) 函数式编程8 偏函数

    偏函数 NOTE 1.int()函数提供额外的base参数,默认值为10.如果传入base参数,就可以做N进制的转换: #!/usr/bin/env python3 import functools ...

  7. python学习,day3:函数式编程,递归和高阶函数

    # coding=utf-8 # Author: RyAn Bi def calc(n): #递归 print(n) if int(n/2) > 0: #设置条件,否则会循环999 次,报错, ...

  8. python学习,day3:函数式编程,局部变量和全局变量

    # coding=utf-8 # Author: RyAn Bi school = 'THU' #全局变量 def change_name(name): global age #在函数中,用globa ...

  9. python学习,day3:函数式编程,*arge,**kwargs

    对于不固定长度的参数,需要使用*arge,**kwargs来调用,区别是*arge是转换为元组,而kwargs转化为字典 # coding=utf-8 # Author: RyAn Bi def te ...

随机推荐

  1. 转:DSP学习经验

    转载:http://www.cnblogs.com/MrYang/archive/2010/12/21/1913035.html

  2. mobile优化

    原文: http://queue.acm.org/detail.cfm?id=2510122 译文: http://www.w3cfuns.com/forum.php?mod=viewthread&a ...

  3. Java 多线程之龟兔赛跑(文件夹——读取文件——时间)

    版权声明:本文为博主原创文章,未经博主允许不得转载. 描述: 乌龟和兔子(各自是一个Java线程)在我们的电脑上赛跑,我们为它们指定一个跑道(本地文件系统上的一个目录,该目录包含子目录).跑的规则是读 ...

  4. PullToRefreshListView组件的OnItemClickListener中的position下标问题

    /** * Pass-through method for {[url=home.php?mod=space&uid=91636]@link[/url] PullToRefreshBase#g ...

  5. 【HDOJ】1315 Basic

    这道题目巨坑啊,注意__int64,int wa了一个下午. #include <cstdio> #include <cstring> #include <cstdlib ...

  6. oschina大数据开源软件

    Hadoop 图形化用户界面 Hue 大数据可视化工具 Nanocubes 企业大数据平台 RedHadoop 大数据查询引擎 PrestoDB Hadoop集群监控工具 HTools 安全大数据分析 ...

  7. SGU 0438 The Glorious Karlutka River =) 动态流

    题目大意:有一条东西向流淌的河,宽为W,河中有N块石头,每块石头的坐标(Xi, Yi)和最大承受人数Ci已知.现在有M个游客在河的南岸,他们想穿越这条河流,但是每个人每次最远只能跳D米,每跳一次耗时1 ...

  8. SQL-Duplicate Emails

    思路: 两种思路,可以给当成两个表也可以给当成一张表来做 group by就是按照某个属性给表分个组,然后having语句的含义是“对于每一个group”怎么怎么样 补充知识:count(column ...

  9. SYNATXAHIGHLIGHTER IN WLW HAS PROBLEMS

    System.Reflection.TargetInvocationException: 调用的目标发生了异常. ---> System.ArgumentException: 字体“Consol ...

  10. (转)Maven实战(二)构建简单Maven项目

    上一节讲了maven的安装和配置,这一节我们来学习一下创建一个简单的Maven项目 1. 用Maven 命令创建一个简单的Maven项目 在cmd中运行如下命令: mvn archetype:gene ...