据我所知,该range()函数实际上是Python 3中的一个对象类型,它可以动态生成其内容,类似于生成器.
在这种情况下,我预计下面的行会花费大量的时间,因为为了确定1千万亿是否在该范围内,必须生成一个千万亿的值:
1000000000000000 in range(1000000000000001)
Run Code Online (Sandbox Code Playgroud)
此外:似乎无论我添加多少个零,计算或多或少都需要相同的时间(基本上是瞬时的).
我也试过这样的事情,但计算仍然几乎是即时的:
1000000000000000000000 in range(0,1000000000000000000001,10) # count by tens
Run Code Online (Sandbox Code Playgroud)
如果我尝试实现自己的范围功能,结果就不那么好了!!
def my_crappy_range(N):
i = 0
while i < N:
yield i
i += 1
return
Run Code Online (Sandbox Code Playgroud)
range()在引擎盖下做的对象是什么让它如此之快?
选择Martijn Pieters的答案是因为它的完整性,但也看到了abarnert的第一个答案,可以很好地讨论在Python 3中range成为一个完整的序列意味着什么,以及关于__contains__Python实现中函数优化的潜在不一致的一些信息/警告.abarnert的另一个答案更详细,并为那些对Python 3中的优化背后的历史感兴趣的人提供了链接(并且缺乏xrangePython 2中的优化).poke和wim的答案为感兴趣的人提供了相关的C源代码和解释.
请澄清我对Singleton和Multithreading的疑问:
getInstance()
方法时会发生什么?getInstance() synchronized吗?我听说有一个GHC的分支默认编译为严格的代码,而懒惰可以通过注释启用.(IIRC,他说一家金融公司开发分支并将其用于生产代码.)这是真的吗?我找不到它.
该人士还认为,严格评估比懒惰评估(默认情况下)更实用的观点越来越受到人们的认可.我没有在Haskell邮件列表中找到这个确认,但也许这是因为那里的人不是那种以实践为导向的?
所有我觉得严格的Haskell就像明确的东西$!和rnf.虽然我发现惰性评估非常优雅,但我想在Haskell中开发一个程序,我希望避免空间泄漏,并希望获得可预测的性能.
免责声明:我不是要严格要求,我只想看看严格的Haskell或类似的东西.
我记得看到一个演示文稿,其中SPJ说懒惰评估迫使他们保持Haskell纯粹(或沿着那条线).我经常看到许多Haskellers说同样的话.
所以,我想了解懒惰的评估策略是如何迫使他们保持Haskell纯粹而不是严格的评估策略?
因此,这种惰性求值的概念被广泛使用,尤其是在阅读函数式编程、Java 流等内容时。
流是惰性的;仅在启动终端操作时才执行对源数据的计算,并且仅在需要时消耗源元素。
哈斯克尔很懒。这意味着除非另有明确说明,Haskell 不会执行函数并计算事物,直到它真正被迫向您显示结果为止。
现在我的理解是,如果我有一个数据列表,我希望对其执行 N 次操作,那么惰性求值只会对整个列表进行 1 次传递,而不是 N 次。为什么这如此理想?在我看来,对单个列表进行 N 次传递所导致的操作次数与对列表进行 1 次传递但对列表中包含的每个元素执行 N 次操作的操作次数相同。
我的问题是:
有人可以以与语言无关的方式回答这个问题吗,因为我对这个概念而不是特定的语言更好奇。
在检查代码时,有时我会看到诸如lazyLoad, lazyActivation, lazyInit,之类的词LazyValue。我目前正在编写 Java 代码,Java 中的大多数命名约定都是在许多来源中指定的,但并不懒惰。所以我想知道“懒惰/懒惰”是否是一种约定,它是什么意思。
懒惰评估被认为是一种延迟流程直到第一次需要的方式.这往往会避免重复评估,这就是为什么我认为这样做的速度要快得多.像Haskell(和JavaScript ..?)这样的函数语言内置了这个功能.
但是,我不明白为什么和为什么其他"正常"方法(即相同的功能但不使用惰性评估)更慢..这些其他方法如何以及为什么重复进行评估?有人可以通过提供简单的例子并解释每种方法的机制来详细说明这一点吗?
另外,根据Wikipedia关于懒惰评估的页面,这些被认为是这种方法的优点:
但是,我们可以控制所需的计算并避免重复相同的计算吗?(1)我们可以使用ie链接列表来创建无限数据结构(2)我们可以做(3)已经.. ??? 我们可以定义类/模板/对象并使用它们而不是原语(即JavaScript).
另外,在我看来(至少从我见过的案例中),懒惰的评估与递归和使用"头部"和"尾部"(以及其他)概念密切相关.当然,有些情况下递归是有用的,但懒惰的评价不仅仅是......?不仅仅是一种解决问题的递归方法..?Streamjs是一个JavaScript库,它使用递归和一些其他简单的操作(头部,尾部等)来执行惰性求值.
看来我无法理解它...
在此先感谢任何贡献.
recursion performance haskell lazy-evaluation lazy-initialization
我是Haskell的新手,我正在为我的Programming Languages课写一篇论文.我想用一些示例代码演示Haskell的懒惰,但我不确定我所看到的是否实际上是懒惰.
doubleMe xs = [x*2 | x <- xs]
Run Code Online (Sandbox Code Playgroud)
在ghci:
let xs = [1..10]
import Debug.Trace
trace (show lst) doubleMe (trace (show lst) doubleMe (trace (show lst) doubleMe(lst)))
Run Code Online (Sandbox Code Playgroud)
输出:
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[1,2,3,4,5,6,7,8,9,10]
[8,16,24,32,40,48,56,64,72,80]
Run Code Online (Sandbox Code Playgroud)
感谢您的时间和帮助!
haskell ×5
performance ×2
evaluation ×1
ghc ×1
java ×1
java-stream ×1
python ×1
python-3.x ×1
quicksort ×1
range ×1
recursion ×1
scala ×1
singleton ×1