跟老齐学Python之大话题小函数(1)


Posted in Python onOctober 10, 2014

开篇就要提到一个大的话题:编程范型。什么是编程范型?引用维基百科中的解释:

编程范型或编程范式(英语:Programming paradigm),(范即模范之意,范式即模式、方法),是一类典型的编程风格,是指从事软件工程的一类典型的风格(可以对照方法学)。如:函数式编程、程序编程、面向对象编程、指令式编程等等为不同的编程范型。
编程范型提供了(同时决定了)程序员对程序执行的看法。例如,在面向对象编程中,程序员认为程序是一系列相互作用的对象,而在函数式编程中一个程序会被看作是一个无状态的函数计算的串行。

 

正如软件工程中不同的群体会提倡不同的“方法学”一样,不同的编程语言也会提倡不同的“编程范型”。一些语言是专门为某个特定的范型设计的(如Smalltalk和Java支持面向对象编程,而Haskell和Scheme则支持函数式编程),同时还有另一些语言支持多种范型(如Ruby、Common Lisp、Python和Oz)。

 

编程范型和编程语言之间的关系可能十分复杂,由于一个编程语言可以支持多种范型。例如,C++设计时,支持过程化编程、面向对象编程以及泛型编程。然而,设计师和程序员们要考虑如何使用这些范型元素来构建一个程序。一个人可以用C++写出一个完全过程化的程序,另一个人也可以用C++写出一个纯粹的面向对象程序,甚至还有人可以写出杂揉了两种范型的程序。

不管看官是初学者还是老油条,都建议将上面这段话认真读完,不管理解还是不理解,总能有点感觉的。

这里推荐一篇文章,这篇文章来自网络:《主要的编程范型》

扯了不少编程范型,今天本讲要讲什么呢?今天要介绍几个python中的小函数,这几个函数都是从函数式编程借鉴过来的,它们就是:

filter、map、reduce、lambda、yield

有了它们,最大的好处是程序更简洁;没有它们,程序也可以用别的方式实现,只不过麻烦一些罢了。所以,还是能用则用之吧。

lambda

lambda函数,是一个只用一行就能解决问题的函数,听着是多么诱人呀。看下面的例子:

>>> def add(x):     #定义一个函数,将输入的变量增加3,然后返回增加之后的值

...     x +=3

...     return x

... 

>>> numbers = range(10)

>>> numbers

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]  #有这样一个list,想让每个数字增加3,然后输出到一个新的list中
>>> new_numbers = []

>>> for i in numbers:

...     new_numbers.append(add(i))  #调用add()函数,并append到list中

... 

>>> new_numbers

[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

 在这个例子中,add()只是一个中间操作。当然,上面的例子完全可以用别的方式实现。比如:

>>> new_numbers = [ i+3 for i in numbers ]

>>> new_numbers

[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

 首先说明,这种列表解析的方式是非常非常好的。

但是,我们偏偏要用lambda这个函数替代add(x),如果看官和我一样这么偏执,就可以:

>>> lam = lambda x:x+3

>>> n2 = []

>>> for i in numbers:

...     n2.append(lam(i))

... 

>>> n2

[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

 这里的lam就相当于add(x),请看官对应一下,这一行lambda x:x+3就完成add(x)的三行(还是两行?),特别是最后返回值。还可以写这样的例子:

>>> g = lambda x,y:x+y  #x+y,并返回结果

>>> g(3,4)

7

>>> (lambda x:x**2)(4)  #返回4的平方

16

 通过上面例子,总结一下lambda函数的使用方法:
 •在lambda后面直接跟变量
 •变量后面是冒号
 •冒号后面是表达式,表达式计算结果就是本函数的返回值
 
为了简明扼要,用一个式子表示是必要的:

lambda arg1, arg2, ...argN : expression using arguments

 要特别提醒看官:虽然lambda 函数可以接收任意多个参数 (包括可选参数) 并且返回单个表达式的值,但是lambda 函数不能包含命令,包含的表达式不能超过一个。不要试图向 lambda 函数中塞入太多的东西;如果你需要更复杂的东西,应该定义一个普通函数,然后想让它多长就多长。

就lambda而言,它并没有给程序带来性能上的提升,它带来的是代码的简洁。比如,要打印一个list,里面依次是某个数字的1次方,二次方,三次方,四次方。用lambda可以这样做:

>>> lamb = [ lambda x:x,lambda x:x**2,lambda x:x**3,lambda x:x**4 ]

>>> for i in lamb:

...     print i(3),

... 

3 9 27 81

 lambda做为一个单行的函数,在编程实践中,可以选择使用。根据我的经验,尽量少用,因为它或许更多地是为减少单行函数的定义而存在的。

map

先看一个例子,还是上面讲述lambda的时候第一个例子,用map也能够实现:

>>> numbers

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]      #把列表中每一项都加3
>>> map(add,numbers)                #add(x)是上面讲述的那个函数,但是这里只引用函数名称即可

[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
>>> map(lambda x: x+3,numbers)      #用lambda当然可以啦

[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

 map()是python的一个内置函数,它的基本样式是:map(func, seq),func是一个函数,seq是一个序列对象。在执行的时候,序列对象中的每个元素,按照从左到右的顺序,依次被取出来,并塞入到func那个函数里面,并将func的返回值依次存到一个list中。

在应用中,map的所能实现的,也可以用别的方式实现。比如:

>>> items = [1,2,3,4,5]

>>> squared = []

>>> for i in items:

...     squared.append(i**2)

... 

>>> squared

[1, 4, 9, 16, 25]
>>> def sqr(x): return x**2

... 

>>> map(sqr,items)

[1, 4, 9, 16, 25]
>>> map(lambda x: x**2,items)

[1, 4, 9, 16, 25]
>>> [ x**2 for x in items ]     #这个我最喜欢了,一般情况下速度足够快,而且可读性强

[1, 4, 9, 16, 25]

 条条大路通罗马,以上方法,在编程中,自己根据需要来选用啦。

在以上感性认识的基础上,在来浏览有关map()的官方说明,能够更明白一些。

map(function, iterable, ...)
Apply function to every item of iterable and return a list of the results. If additional iterable arguments are passed, function must take that many arguments and is applied to the items from all iterables in parallel. If one iterable is shorter than another it is assumed to be extended with None items. If function is None, the identity function is assumed; if there are multiple arguments, map() returns a list consisting of tuples containing the corresponding items from all iterables (a kind of transpose operation). The iterable arguments may be a sequence or any iterable object; the result is always a list.

理解要点:
 •对iterable中的每个元素,依次应用function的方法(函数)(这本质上就是一个for循环)。
 •将所有结果返回一个list。
 •如果参数很多,则对么个参数并行执行function。
 
例如:

>>> lst1 = [1,2,3,4,5]

>>> lst2 = [6,7,8,9,0]

>>> map(lambda x,y: x+y, lst1,lst2)     #将两个列表中的对应项加起来,并返回一个结果列表

[7, 9, 11, 13, 5]

 请看官注意了,上面这个例子如果用for循环来写,还不是很难,如果扩展一下,下面的例子用for来改写,就要小心了:

>>> lst1 = [1,2,3,4,5]

>>> lst2 = [6,7,8,9,0]

>>> lst3 = [7,8,9,2,1]

>>> map(lambda x,y,z: x+y+z, lst1,lst2,lst3)

[14, 17, 20, 15, 6]

 这才显示出map的简洁优雅。

预告:下一讲详解reduce和filter

Python 相关文章推荐
python开发的小球完全弹性碰撞游戏代码
Oct 15 Python
详解Python2.x中对Unicode编码的使用
Apr 03 Python
python爬虫框架scrapy实战之爬取京东商城进阶篇
Apr 24 Python
Python 闭包的使用方法
Sep 07 Python
[原创]Python入门教程4. 元组基本操作
Oct 31 Python
python 使用re.search()筛选后 选取部分结果的方法
Nov 28 Python
python3.6环境安装+pip环境配置教程图文详解
Jun 20 Python
TFRecord文件查看包含的所有Features代码
Feb 17 Python
Python3 操作 MySQL 插入一条数据并返回主键 id的实例
Mar 02 Python
python图片剪裁代码(图片按四个点坐标剪裁)
Mar 10 Python
django model的update时auto_now不被更新的原因及解决方式
Apr 01 Python
让Django的BooleanField支持字符串形式的输入方式
May 20 Python
Python警察与小偷的实现之一客户端与服务端通信实例
Oct 09 #Python
python中二维阵列的变换实例
Oct 09 #Python
python实现每次处理一个字符的三种方法
Oct 09 #Python
Python正则表达式匹配ip地址实例
Oct 09 #Python
Python数据结构之Array用法实例
Oct 09 #Python
python中pygame模块用法实例
Oct 09 #Python
python根据文件大小打log日志
Oct 09 #Python
You might like
优化PHP代码技巧的小结
2013/06/02 PHP
php实现的ping端口函数实例
2014/11/12 PHP
PHP仿qq空间或朋友圈发布动态、评论动态、回复评论、删除动态或评论的功能(上)
2017/05/26 PHP
ThinkPHP 框架实现的读取excel导入数据库操作示例
2020/04/14 PHP
编辑浪子版表单验证类
2007/05/12 Javascript
jQuery 使用手册(七)
2009/09/23 Javascript
IE中的File域无法清空使用jQuery重设File域
2014/04/24 Javascript
jquery实现的图片点击滚动效果
2014/04/29 Javascript
Grunt入门教程(自动任务运行器)
2015/08/06 Javascript
JS组件Bootstrap实现弹出框和提示框效果代码
2015/12/08 Javascript
利用JQuery写一个简单的异步分页插件
2016/03/07 Javascript
探讨:JavaScript ECAMScript5 新特性之get/set访问器
2016/05/05 Javascript
由简入繁实现Jquery树状结构的方法(推荐)
2016/06/10 Javascript
原生node.js案例--前后台交互
2017/02/20 Javascript
Vue.js实战之组件之间的数据传递
2017/04/01 Javascript
Vuex 进阶之模块化组织详解
2018/01/12 Javascript
nodejs实现连接mongodb数据库的方法示例
2018/03/15 NodeJs
Vue+Element自定义纵向表格表头教程
2020/10/26 Javascript
JavaScript实现页面高亮操作提示和蒙板
2021/01/04 Javascript
[01:15]《辉夜杯》北京网鱼队巡礼
2015/10/26 DOTA
Python中的字符串查找操作方法总结
2016/06/27 Python
python实现k-means聚类算法
2018/02/23 Python
python实现给微信指定好友定时发送消息
2019/04/29 Python
解决pymysql cursor.fetchall() 获取不到数据的问题
2020/05/15 Python
解决python中import文件夹下面py文件报错问题
2020/06/01 Python
使用pytorch实现论文中的unet网络
2020/06/24 Python
可持续木材、生态和铝制太阳镜:Proof Eyewear
2019/07/24 全球购物
COSETTE官网:奢华,每天
2020/03/22 全球购物
如果让你测试一台高速激光打印机,你都会进行哪些测试
2012/12/04 面试题
个人查摆剖析材料
2014/02/04 职场文书
保证书范文大全
2014/04/28 职场文书
广场舞大赛策划方案
2014/05/31 职场文书
计算机应用专业毕业生求职信
2014/06/03 职场文书
如何书写公司员工保密协议?
2019/06/27 职场文书
详解CSS开发过程中的20个快速提升技巧
2021/05/21 HTML / CSS
FP-growth算法发现频繁项集——构建FP树
2021/06/24 Python