栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

为什么要用Python功能编程?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

为什么要用Python功能编程?

编辑 :由于没有提供更多的解释/示例,我被注释中的任务(部分地,似乎是由FP的狂热者(但不是排他性的))提供的,因此扩大了答案以提供一些解释/示例。

lambda
,更是这样
map
(和
filter
),
最特别的是
reduce
,在几乎没有在Python中,这是一个强烈的多范式语言工作的工具。

lambda
与普通
def
语句相比,主要优点(?)是它可以创建一个 匿名 函数,同时
def
为该函数提供一个名称-
而对于这一非常可疑的优点,您将付出巨大的代价(该函数的主体仅限于一个表达式,即结果函数对象不是可腌制的,缺少名称有时会使理解堆栈跟踪或以其他方式调试问题变得更加困难-
我需要继续吗?!-)。

考虑一下您有时会在“ Python”中使用的最愚蠢的惯用法(带有“吓人的引号”的Python,因为它显然 不是 惯用的Python-
从惯用Scheme之类的音译中很糟糕,就像更频繁地过度使用) Python中的OOP是Java或类似语言的错误音译):

inc = lambda x: x + 1

通过为lambda分配名称,此方法将立即丢弃上述“优点”,并且不会丢失任何缺点!例如,

inc
知道
它的名字-
inc.__name__
是无用的字符串
'<lambda>'
-祝您好运,了解其中的一些堆栈跟踪;-)。在这种简单情况下,实现所需语义的正确Python方法当然是:

def inc(x): return x + 1

现在

inc.__name__
是字符串
'inc'
,这显然是应该的,并且该对象是可腌制的-
语义是相同的(在这种简单的情况下,所需的功能可以轻松地用一个简单的表达式表示)-
def
如果需要,它也可以很容易地进行重构暂时或永久插入语句,例如
print
raise
)。

lambda
是一个表达式的
def
一部分,而是一个语句的一部分-
这是使人们
lambda
有时使用的语法糖的一点点。许多FP爱好者(与许多OOP和程序迷一样)不喜欢Python在表达式和语句之间的合理区分(这是对Command-
Query Separation的一般立场的一部分)。我,我认为,当您使用一种语言时,最好不要“杂乱无章”地使用它- 设计 要使用的方式-
而不是与之抗争。因此我以Python方式编程Python,以示意图(;-)方式编程Scheme,以Fortesque(?)方式编程Fortran,等等:-)。

继续

reduce
-有一条评论声称这
reduce
是计算列表乘积的最佳方法。真的吗?让我们来看看…:

$ python -mtimeit -s'L=range(12,52)' 'reduce(lambda x,y: x*y, L, 1)'100000 loops, best of 3: 18.3 usec per loop$ python -mtimeit -s'L=range(12,52)' 'p=1' 'for x in L: p*=x'100000 loops, best of 3: 10.5 usec per loop

因此,简单,基本,琐碎的循环比执行任务的“最佳方式”快大约两倍(以及更简洁)?-)我猜速度和简洁的优点必须使琐碎的循环成为“最明智的” “对吧?-)

通过进一步牺牲紧凑性和可读性…:

$ python -mtimeit -s'import operator; L=range(12,52)' 'reduce(operator.mul, L, 1)'100000 loops, best of 3: 10.7 usec per loop

…我们 几乎
可以回到最简单,最明显,紧凑和易读的方法(简单,基本,琐碎的循环)容易获得的性能。这

lambda
实际上指出了另一个问题:性能!对于足够简单的操作(例如乘法),与实际执行的操作相比,函数调用的开销相当大-
reduce
(and
map
filter
)通常会迫使您在简单循环,列表推导和生成器表达式中插入此类函数调用允许在线操作的可读性,紧凑性和速度。

也许比上述“为名称分配lambda”反习惯用语更糟,实际上它是以下反习惯用语,例如,按字符串的长度对列表进行排序:

thelist.sort(key=lambda s: len(s))

而不是明显的,可读的,紧凑的,更快的

thelist.sort(key=len)

在这里,使用

lambda
只是插入了一定程度的间接操作-什么都没有产生任何效果,也有很多不好的效果。

使用的动机

lambda
通常是允许使用
map
filter
而不是使用更可取的循环或列表理解,而不是让您在线进行普通的常规计算。当然,您仍然需要支付“间接级别”。不必怀疑“我应该在这里使用listcomp还是地图”,这并不是Python的意思:只是始终使用listcomps,当两者都适用且您不知道选择哪个时,基于“应该有一个,并且最好只有一种明显的做事方式”。您经常会编写无法明智地转换为映射(嵌套循环,
if
子句等)的listcomp,而没有对它的调用
map
不能明智地重写为listcomp。

在Python中,完全正确的函数方法通常包括列表理解,生成器表达式,

itertools
高阶函数,各种伪装的一阶函数,闭包,生成器(有时还包括其他种类的迭代器)。

itertools
作为评论者指出的那样,不包括
imap
ifilter
:所不同的是,像所有itertools,这些是基于流的(像
map
filter
在Python
3建宏,但不同于那些内建在Python 2)。
itertools
提供了一组相互融合且性能出色的构建块:尤其是如果您发现自己可能处理很长(甚至是无穷大!)的序列,则应归功于自己熟悉itertools-
它们的整体文档中的章节有助于您阅读,尤其是食谱很有启发性。

编写自己的高阶函数通常很有用,尤其是当它们适合用作装饰器时(如文档那部分所述的函数装饰器和Python
2.6中引入的类装饰器)。切记在函数装饰器上使用functools.wraps(以保持包裹函数的元数据)!

因此,总结一下……:可以使用

lambda
map
和进行编码的任何事情
filter
,都可以使用
def
(命名函数)和listcomps进行编码(通常不是很方便),并且通常将一个缺口移到生成器,生成器表达式或上
itertools
。更好。
reduce
符合“有吸引力的滋扰”的法律定义…: 几乎从来都不是 适合该工作的工具(这就是为什么它最终不再是Python
3中的内置工具!)。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/650805.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号