用lambda语法漂亮地实现python数组遍历

十一月 20th, 2008 by Soloman | Print 用lambda语法漂亮地实现python数组遍历 | 1,436 views

今天写了一个简单的python脚本,经过朋友提醒,发现能使用lambda语法来使语句更加直观和便于阅读。当然,我学语言一般是从使用开始,所以语言的完整教材我是从没有看过的,也许这个用法在教材里已经说过了。

比如,我们有这样一个问题。有一个数组A = 1,2,3,4,5,6,7。我们想根据该数组生成一个新的数组B,使其包含数组A里的所有奇数。那么我们普通的做法可能是:

>>> arrayA = [1,2,3,4,5,6,7]
>>> arrayB = []
>>> for number in arrayA:
        if number % 2:
            arrayB.append(number)

>>> print arrayB
[1, 3, 5, 7]
>>> 

而lambda语法能大大地优化这个写法。lambda语法其实就是一种用来临时定义函数对象的方法,根据这种语法,我们不需要费事地去重新定义一个函数,而直接就可以用一个表达式来表示一个未命名的函数。让我们看看用lambda语法如何写这段程序吧:

>>> arrayA = [1,2,3,4,5,6,7]
>>> arrayB = [ number for number in arrayA if number % 2 ]
>>> print arrayB
[1, 3, 5, 7]
>>> 

是不是优雅多了?我们把这段代码用括号分成三个部分:

(number) (for number in arrayA) (if number % 2)

第一部分,表面我们的新数组的元素表示为number;第二部分,是说number是取之于数组arrayA的遍历;第三部分,是说是否产生该元素的条件,也就是说当number取2的摸为非0数的时候(也就是奇数),我们选取该number。

了解了这个语法后,我们可以轻松写出一些稍为复杂点的逻辑。

比如,我们有4个人的资料:

>>> person1 = {
	'surname':     'Wang',
	'givename':    'Shawn',
	'age':         16
	}
>>> person2 = {
	'surname':     'Lee',
	'givename':    'How',
	'age':         20
	}
>>> person3 = {
	'surname':     'Lao',
	'givename':    'Suo',
	'age':         25
	}
>>> person4 = {
	'surname':     'Lao',
	'givename':    'Shi',
	'age':         10
	}

这四个人都想去观看成人电影,我们把他们放到一个数组里:

>>> people_who_want_to_watch_av_film = [
	person1, person2, person3, person4
	]

然后,我们检查他们的年龄,产生能够观看的人员的列表,并打印出来:

>>> people_who_can_watch_av_film = [
	'Hi, %s %s, you can watch av!' % (person['surname'], person['givename'])
	for person in people_who_want_to_watch_av_film
	if person['age'] >= 18
	]
>>> for words in people_who_can_watch_av_film: print words

Hi, Lee How, you can watch av!
Hi, Lao Suo, you can watch av!
>>> 

最后,我要严重声明,该例子纯属虚构,如有雷同,纯属巧合!

 

本文有41条评论

  1. 月光下的过客 说: [回复]

    不懂,一点也不明白,没学过,呵呵

  2. 十二星座 说: [回复]

    Hi,老所,you can watch av!

  3. 十二星座 说: [回复]

    晕 我还以为是沙发呢,没想到。。。。

  4. Elton Disney 说: [回复]

    例子不错~~
    话说最近N多人都在学python语言,我也在学,谢过了~~~

  5. leehow 说: [回复]

    我很仔细的看了一下,“Hi, Lee How, you can watch av!”,真是鲜明生动,言简意赅的例子啊…

  6. 大仙 说: [回复]

    那么深奥的东西,需要到以后才能看得懂。

  7. LOKE 说: [回复]

    不懂~不过过来拜摹一下

  8. Yacca 说: [回复]

    学过…但完全米学进去…

  9. iColor 说: [回复]
          for number in arrayA:
                  if number % 2:
                      arrayB.append(number)
    

    能这么干不??

          for number in arrayA:
                      arrayB.append(if number % 2)
    

    下面这句会代码提示吗?要一个一个打的话不更累,还不如用上面的…
    [ number for number in arrayA if number % 2 ]

  10. iColor 说: [回复]

    老所..我回复格式有问题,帮我改一下吧…

  11. iColor 说: [回复]

    @leehow 呵呵,支持一下… -_-!!!

  12. Soloman 说: [回复]

    @iColor

    我帮你在 Python 的解释器里执行一下,你就清楚了,这是运行你代码的结果:

    >>> arrayA = [1,2,3,4,5,6,7]
    >>> arrayB = []
    >>> for number in arrayA:
        arrayB.append(if number % 2)
    
    SyntaxError: invalid syntax
    >>> for number in arrayA:
        arrayB.append(number % 2)
    
    >>> print arrayB
    [1, 0, 1, 0, 1, 0, 1]
    >>>
    

    看到了吗?第一种写法是不支持的,但是如果去掉if,则插入arrayB的都是布尔值,1表示这个数为奇数,0表示偶数。

  13. Soloman 说: [回复]

    @iColor

    再来说说语言风格的问题,同样一个问题,方法一:

    a = [1,2,3,4,5,6,7]
    b = []
    for n in a:
      if n % 2:
        b.append(n)
    

    和方法二:

    a = [1,2,3,4,5,6,7]
    b = [n for n in a if n % 2]
    

    哪一种代码简练呢?哪一种方法更易于阅读呢?

    在方法一中,我们首先定义了两个数组a和b,然后阅读代码的人还要注意到一个循环,然后仔细阅读循环,才知道这是为了设置b而用的。

    在方法二种,阅读代码的人很直观地知道其实我们就是要两个数组,唯一不同的是第一个数组是写出了所有元素,第二个数组用了某些算法来设置数组元素。

    关于代码自动补齐,说实话,我现在已经基本上不用IDE了,文本编辑器足以。有的时候你远程登录到其他机器上的时候,是没有那些花哨的图形IDE的,有个VI或者Emacs就不错了。

    我一向反对专门写程序的文档,我认为最好的程序文档就是代码本身,所以,设计界面的要关注用户体验(UE),写程序的则要关注代码阅读体验。

  14. Shawn 说: [回复]

    老所看来要掀起 python 学习潮

  15. Soloman 说: [回复]

    @Shawn

    呵呵,我只是记录自己学到的一点东西,分享一下。话说python这个语言还真是好用。

  16. Soloman 说: [回复]

    @leehow 希望av这个“关键字”能够为我多加点流量,哈哈

  17. Soloman 说: [回复]

    @Yacca 没事,你有python这个超能力的,只是你现在还不会使用,如同Peter以前:)

  18. Soloman 说: [回复]

    @Yacca 你啥时能不能也写写 Mentist 的评论?

  19. Shawn 说: [回复]

    @Soloman Yacca 没有看 The Mentalist,昨天那集挺好看的。
    AV 在你这里不能算关键字。。。

  20. 老时 说: [回复]

    我不懂,我来捧场的。

  21. Soloman 说: [回复]

    @Shawn 昨天那个神婆那集一般,上集那个赌场的比较爽。

  22. Soloman 说: [回复]

    @老时 你的乳沟妹妹泡的怎么样了?

  23. 老时 说: [回复]

    有点意思,这两天就写出来。

  24. Jor 说: [回复]

    哈哈!!仔细看了下。例子真好……

  25. iColor 说: [回复]

    @Soloman 了解了解,
    这句我当时脑袋怎么想的都不知道了,,,
    arrayB.append(if number % 2)
    括号里应该是需要一个值的,,,

  26. daniel 说: [回复]

    (number) (for number in arrayA) (if number % 2)
    很帅,加上括号更帅,可读性好了。。。
    貌似这个很像SQL查询语句哈。。。。 不知道lambda是不是从SQL查询中找到的灵感
    PS:LAMBDA 不懂哈 ,第一听说

  27. Soloman 说: [回复]

    @daniel

    lambda是一种语法,用来隐式定义函数对象的,目前python语言和ruby语言都支持。

    对于C++,以前如果要写一个STL的算法,比如for_each算法,需要你自己去定义一个函数对象functor,现在有了boost lambda,就不需要定义函数对象了,直接用lambda语法就可以定义了,所以非常方便,也便于阅读。

    你可以去搜索下“python lambda”或者”boost lambda”。

  28. Soloman 说: [回复]

    @daniel 这个括号是我为了大家方便阅读加上的,本来不应该有的:)

  29. basil 说: [回复]

    你这个例子,寒一下! 小心让小朋友看到……

  30. Soloman 说: [回复]

    @basil 我觉得这个例子很好啊,让小朋友们从小就了解没满18岁不能去看有些电影的:)

  31. Soloman 说: [回复]

    @Yacca python 编程的一个小小语法.

  32. u88 说: [回复]

    不错,学习一下.

  33. u88 说: [回复]

    不错.写的可以.

  34. calf 说: [回复]

    这个。。。。。这个难道不是python里面最最基本的语法么。。。

  35. 不是吧 说: [回复]

    这个不叫lamda吧

添加评论 (支持Gravatar头像)

注意: 评论者允许使用'@user空格'的方式将自己的评论通知另外评论者。例如, ABC是本文的评论者之一,则使用'@ABC '(不包括单引号)将会自动将您的评论发送给ABC。使用'@all ',将会将评论发送给之前所有其它评论者。请务必注意user必须和评论者名相匹配(大小写一致)。

实时评论预览