我最近读到map
了Python 3的一个好处是它很懒。那就更好了
map(lambda x: x**2, range(10**100))
而不是
[x**2 for x in range(10**100)]
我很好奇的是如何使用这种懒惰。如果生成映射对象,例如,如何访问生成的操作/列表中的特定元素。在map
我所见过的几乎所有文档中,他们都会做类似print(map(...))
或的事情for i in map(...)
(据我所知),它放弃了惰性概念,因为它隐式将地图转换为列表。
我想我正在寻找的是能够以与range
我可以懒惰地懒惰x = range(10**100)
地生成地图对象类似的方式使用地图对象的能力,并且可以在x[10000]
没有巨大计算量的情况下懒惰地生成地图对象。
如果这个概念不存在,那么map
懒惰有什么好处?如果您始终需要将其转换为某些非惰性对象(如列表),那么为什么map
惰性是重要的呢?
您在这里比较苹果和桔子。range
是 不是
只是一个懒惰的迭代。它是一个特定的对象,其内容满足特定的法律,该法律允许支持许多操作而无需在内存中实际构建巨大的序列。这是因为的第n个元素range
基本上只是start + n*step
(模stop
,符号等)
但是map
它 意味着 可以使用 任何 功能f
。特别是功能可能具有共享/全局状态,这已经失去了在map(f, something)[100]
不执行100个功能调用的情况下能够执行的任何机会。不这样做会破坏结果的 正确性 。
map
“懒惰”只是意味着它不会立即生成完整的结果列表,而是等待您要求下一个结果,然后再调用f
并产生它。这样可以避免在代码中生成不必要的列表,例如:
for x in map(f, iterable):
# do something with x
如果map
急切的话iterable
,html" target="_blank">执行循环将消耗两倍的内存,而懒惰map
的话,所需的唯一空间x
基本上是。
此外,它可以调用map
的 无限iterables
一样count()
。这显然导致程序永无休止地做某事,或者在某个时候您可以停止调查map
。渴望map
不能处理这种情况。
如果您想使用仅适用于纯功能并且允许随机访问的受限映射,则可以编写自己的类:
class PureMap:
def __init__(self, function, sequence):
self._f = function
self._sequence = sequence
def __iter__(self):
return map(self._f, self._sequence)
def __getitem__(self, i):
return self._f(self._sequence[i])
# etc.
但是,即使在这种情况下,您仍然会遇到一些问题:
如果sequence
实际上是iterable
,则要获取第n个元素,则必须消耗前n个元素。之后,您必须将它们作为序列存储在类中,以备将来使用。但这已经违反了整件事的目的,因为这样做PureMap(f, sequence)[1000]
需要您始终将1000
元素存储在内存中, 即使它避免了对的999
调用f
。
您要避免f
在同一元素上多次调用。这意味着您还必须跟踪已计算出哪个元素,而未计算出哪个元素。
可以实现所需目标的唯一情况如下:
range
,它允许随机访问而不必产生其他元素当所有这些假设都满足时,您可以拥有一个“像range
”一样工作的地图对象。
问题内容: 例如,如果我有以下语句: 如果foo1为true,python将检查foo2的条件吗? 问题答案: 是的,Python懒惰地评估布尔条件。 该文件说, 表达式x和y首先计算x;如果x为假,则返回其值;否则,将评估y并返回结果值。 表达式x或y首先计算x; 如果x为true,则返回其值;否则,将评估y并返回结果值。
我正在阅读HadleyWickhams关于Github的书,特别是关于懒惰评估的这一部分。在那里,他给出了一个懒惰求值结果的例子,在函数的添加部分。让我引用这一点: 这个[惰性评估]在使用lApplication或循环创建闭包时很重要: x在您第一次调用其中一个加法器函数时被延迟计算。此时,循环完成,x的最终值为10。因此,所有加法器函数都会在其输入中添加10,可能不是您想要的!手动强制评估解决了
问题内容: 我在python应用程序中使用标准的python日志记录模块: 问题是,尽管未启用调试级别,但在每次循环迭代时都会评估该愚蠢的日志消息,这会严重损害性能。 有什么解决办法吗? 在C ++中,我们提供了提供以下宏的软件包: 有效评估为 但是,由于Python(AFAIK)中没有宏,是否有一种有效的日志记录方法? 问题答案: 日志记录模块已经对您要执行的操作提供了部分支持。做这个: …代替
我已经写了两个版本的nqueens问题,我认为它们应该有相似的效率,但事实并非如此。我认为这是由于哈斯克尔的懒惰评估行为。有人能解释一下下面的例子是如何工作的吗, 您可以通过调用nqueens1 8 8或nqueens2 8 8对其进行评估,以对大小为8的板进行评估。 虽然nqueens2工作效率很高,但nqueens1存在性能问题。我相信这是因为递归调用(nqueens n(k-1))被多次评估
问题内容: 什么是Python中的惰性评估? 一个网站说: 在Python 3.x中,该函数返回一个特殊的范围对象,该对象按需计算列表元素(延迟或延迟评估): 这是什么意思? 问题答案: 由(或在Python2.x中)返回的对象被称为惰性迭代。 生成器没有将整个范围存储在内存中,而是存储的定义并仅在需要时才计算下一个值(又称惰性求值)。 本质上,生成器允许您返回类似于结构的列表,但是这里有一些区别
问题内容: 抱歉,这听起来像是一个很愚蠢的问题。 但是我在网上搜索了Google,还专门搜索了php.net网站和stackoverflow.com网站。 我知道PHP 在使用运算符时会进行 短路惰性评估 ,但是在PHP手册中它在何处清晰明了? 我发现只有Wikipedia作为唯一的“可信赖”资源,它说PHP对这些运算符进行了惰性评估。 问题答案: 我可以找到关于PHP的短路实现的“官方”最接近的