美文网首页
寻找符合Python风格的求和方式

寻找符合Python风格的求和方式

作者: MatsuiRakuyo | 来源:发表于2018-01-15 14:31 被阅读0次

本文摘自《流畅的Python》(《FluentPython》),作者Luciano Ramalho,译者安道 吴珂


=============

序言

就像“什么是美”没有确切的答案一样,“什么是Python风格”也没有标准答案。如果回答“地道的Python”,不能让人100%满意,因为对你来说是“地道的”,在我看来却可能不是。但我可以肯定的是,“地道”并不是指使用最鲜为人知的语言特性。

先决条件

  • 归约函数(reduce、sum、any、all)将序列或有限的迭代对象变成一个聚合结果
  • reduce函数在目前的更新中已经被收进functools包中了
  • 函数签名reduce(function, iterable, initializer)
    其中第三个参数initializer是可选的。它避免了空序列抛出异常,如果令了这个参数,将从这个参数开始。(一般为恒等值,如+|^等令为1,+ &令为0)。
    function是一个接收两个参数的函数。
  • 调用的一般过程为:如序列[1,2,3,4,5]
    fun(1,2) (=a)
    fun(a, 3) (=b)
    fun(b, 4) etc...

问题提出

Python-list上有一篇题为“Pythonic Way to Sum n-th List Element?”(链接似已失效?)的话题与本篇讨论的reduce函数有关。
该话题发起人Guy Middleton说他不喜欢使用lambda表达式,问如下方案可否改进:

>>>my_list = [[1, 2, 3], [40, 50, 60], [9, 8, 7]]
>>>import functools
>>>functools.reduce(lambda a,, b: a+b, [sub[1] for sub in my_list])
60

这段代码包含了:lambda、reduce和列表推导。这对于讨厌lambda和看不上列表推导的人两边不讨好——这两种人都很多。如果使用lambda,或许就不应该使用列表推导——过滤除外,但这不是过滤((for x in list if x > 0) 其中if就是过滤表达式)。


=============

本书的作者给出的方案是:

>>> functools.reduce(lambda a, b: a + b[1], my_list, 0)
60

但作者表示不会在真实代码如此写,(因为他也不喜欢lambda表达式)。此处仅仅是为了举例说明不使用列表推导怎么做。


=============

第一个答案

,来自Fernando Perez,IPython的创建者,强调了NumPy支持n维数组和n维切片:

>>> import numpy as np
>>>my_array = np.array(my_list)
>>>np.sum(my_array[:, 1]
60

(即一维全体,二维的下标1元素)


=============

第二个答案

,Guy Middleton推崇Paul Rubin和Skip Montanaro给出的下述方案:

>>> import operator
>>> functools.reduce(operator.add, my_list, 0)
60

其中,operator库中包含诸如add, xor等常用数字运算函数,包含两个参数


=============

以及

,EvanSimpson问道:"这样做有什么错?"

>>> total = 0
>>> for sub in my_list:
...            total += sub[1]
>>>total
60

foreach循环。
许多人都觉得这也很符合Python风格。Alex Martelli甚至说,Guido或许就会这么做。
作者喜欢这段代码,更喜欢David Eppstein对此给出的评论:

如果你想计算列表各个元素的和,写出的代码应该看起来像是在“计算元素之和”,而不是“迭代元素,维护一个变量t,再执行一系列求和操作”。如果不能站在一定高度上表明意图,让语言去关注低层次操作,那么要高级语言干嘛?

之后Alex Martelli又建议:

求和操作经常需要,我不介意Python提供一个这样的内置函数。但是,在我看来,“reduce(operator..add,...”不是好方法(作为一名APL老程序员和FP语言的爱好者,我应该喜欢,但我并不喜欢)。


随后

Alex建议提供并实现了sum()函数并在之后的Python2.3中内置了。因此,Alex喜欢的句法变成了标准:(列表推导,仅能生成list)

>>> sum([sub[1] for sub in my_list])
60

下一年年末(2004年11月),Python2.4发布,这一版引入了生成器表达式。因此,作者建议,当前这个问题最符合Python风格的答案是:(生成任何类型的序列)

>>> sum(sub[1] for sub in my_list)
60

这样写不仅比reduce函数可读性更强,而且还避免了空序列导致的陷阱:sum([])的结果是0,就这么简单
在这次讨论中,Alex Martelli指出,Python2内置的reduce函数成事不足败事有余,因为他推荐的地道编程方式难以理解。他的观点最优说服力:Python3把reduce函数移到functools模块中了。

end

相关文章

  • 寻找符合Python风格的求和方式

    本文摘自《流畅的Python》(《FluentPython》),作者Luciano Ramalho,译者安道 吴珂...

  • 符合 Python 风格的对象

    对象表现形式 repr()从开发者的角度,背后是 _repr_() str()从用户的角度,背后是 _str_()...

  • 符合Python风格的对象

    基于 Python 的数据模型,自定义类型可以实现和内置类型一样自然的行为,实际上靠的是 鸭子类型。 鸭子类型:按...

  • Python 10 个习惯

    Python 使用习惯是指那些经常被使用的语法、语义和结构,这样写更加符合 Python 风格(pythonic)...

  • 编写python的代码规范- PEP 8 风格指南

    PEP 8 风格指南 中文版 此外: Pylint 是一款可以分析Python源码是否符合 PEP 8 风格的工具...

  • 简约时尚办公室装修风格

    办公室装修风格要选择与整个建筑风格相协调,不需要太繁琐的装饰,颜色尽量运用简单、符合现代人的心理需求和工作需求。在...

  • 为什么 切片和区间会忽略最后一个元素

    摘自 《流程的Python》 在切片和区间操作里不包含区间范围的最后一个元素是 Python 的风格,这个习惯符合...

  • mitmproxy使用心得

    mitmproxy更符合开发查看习惯,可以结合python脚本修改请求和响应,功能强大。1.多使用?查看快捷键 常...

  • Effective python

    用pythonic方式思考 确认使用的python的版本, 优先使用python3 遵守PEP8风格, 保护属性_...

  • fluent python-第 9 章 符合Python风格的对

    绝对不要使用两个前导下划线, 这是很烦人的自私行为。 9.1 对象表示形式 每门面向对象的语言至少都有一种获取对象...

网友评论

      本文标题:寻找符合Python风格的求和方式

      本文链接:https://www.haomeiwen.com/subject/xozroxtx.html