讲解 在 C# 基础库中经常可以看到很多方法返回值是 IEnumerable 类型,那么为什么返回 IEnumerable 而不是返回 IList、ICollection 或 List 类型呢?...好处是可以像上面演示的那样尽可能即时地给用户响应。还有一个好处是可以提高内存使用效率。通过 yield 返回的 IEnumerable 类型表示这是一个可以被遍历的数据集合。...迭代器方法则是依次返回多个值给调用者,并在这期间保留局部资源,等所有值都返回结束时再释放掉局部资源,这些返回的值将形成一组序列被调用者使用。 迭代器可以用于方法、属性或索引器中。...迭代器中的 yield 语句分为两种: yeild return,把程序控制权交回调用者并保留本地状态,调用者拿到返回的值继续往后执行。...yeild break,用于告诉程序当前序列已经结束,相当于正常代码块的 return 语句(迭代器中直接使用 return 是非法的)。
λ演算可以接受函数当作输入(参数)和输出(返回值)。 和指令式编程相比,函数式编程的思维方式更加注重函数的计算。它的主要思想是把问题的解决方案写成一系列嵌套的函数调用。...直到 Curry Haskell 1927 在普林斯顿大学当讲师时重新发现了 Moses Schönfinkel 关于组合子逻辑的成果。...在惰性计算中,表达式不是在绑定到变量时立即计算,而是在求值程序需要产生表达式的值时进行计算。...,然后不断的展开,直到最后到达了终止的n==0,这是递归的原则之一,就是在递归的过程中,传递的参数一定要不断的接近终止条件,在上面的例子中就是n的值不断减少,直至最后为0。...引用透明性 函数程序通常还加强引用透明性,即如果提供同样的输入,那么函数总是返回同样的结果。就是说,表达式的值不依赖于可以改变值的全局状态。这样我们就可以从形式上逻辑推断程序行为。
通常的循环可能会依据一个等差数值步进过程(如 Pascal),或由用户来定义迭代步骤和中止条件(如 C ),Python 的 for 语句依据任意序列(链表或字符串)中的子项,按它们在序列中的顺序来进行迭代...print(i) ... 0 1 2 3 4 range(10) 生成了一个包含 10 个值的链表,它用链表的索引值填充了这个长度为 10 的列表,所生成的链表中不包括范围中的结束值。...函数引用的实际参数在函数调用时引入局部符号表,因此,实参总是 传值调用 (这里的 值 总是一个对象 引用 ,而不是该对象的值)。...如果你使用过其他语言,你可能会反对说:fib 不是一个函数,而是一个方法,因为它并不返回任何值。...如果你确实想看到这个值的输出内容,请使用 print() 函数: >>> fib(0) >>> print(fib(0)) None 定义一个返回斐波那契数列数字列表的函数,而不是打印它,是很简单的:
最近有空就在看Haskell,真是越看越觉得这个语言有意思。在知乎(原回答@阅千人而惜知己的)找到了一份很有意思的求素数代码,非常简洁,我觉得很能体现这个语言的特点。...,这段代码的结果并不是一个内容为2-maxn内素数的数组,而是记录2-maxn间的数字是不是素数的一个布尔数组。...那么,如果是放在同样具有列表解析的Python中,又能怎么写呢?...while True: n = next(it) # 返回序列的第一个数 yield n it = filter(_not_divisible...(n), it) # 构造新序列 看来看去,似乎Haskell的版本真的很简单舒服。
Python 中的 for 语句并不总是对算术递增的数值进行迭代(如同 Pascal),或是给予用户定义迭代步骤和暂停条件的能力(如同 C),而是对任意序列进行迭代(例如列表或字符串),条目的迭代顺序与它们在序列中出现的顺序一致...print(i) ... 0 1 2 3 4 给定的终止数值并不在要生成的序列里;range(10) 会生成10个值,并且是以合法的索引生成一个长度为10的序列。...在函数被调用时,实际参数(实参)会被引入被调用函数的本地符号表中;因此,实参是通过 按值调用 传递的(其中 值 始终是对象 引用 而不是对象的值)。...一般来说解释器不会打印出单独的返回值 None ,如果你真想看到它,你可以使用 print() >>> fib(0) >>> print(fib(0)) None 写一个返回斐波那契数列的列表(而不是把它打印出来...它可以测试一个序列是否包含某个值。 默认值是在 定义过程 中在函数定义处计算的,所以: i = 5 def f(arg=i): print(arg) i = 6 f() 会打印 5。
所有序列类型都是位置索引的(从0到长度−1),并且除了字符串,都可以包含任意类型的对象,在同一个序列中包括多种类型的对象。字符串和元组是不可变的,使得它们成为字典的键的完美候选者。...>>> print(msg) Input Input程序可以提示用户输入。所有输入都存储为字符串。 提示输入值 >>> name = input("What's your name?...>>> dimensions = (1920, 1080) 七、字典 字典存储在片段信息之间的建立联系。字典中的每一个项都是一个键-值对。当提供一个键时,Python将返回与该键相关联的值。...如果需要的键不在字典中,就会出现错误。 还可以使用get()方法,如果键不存在,该方法将返回None,而不是错误。如果键不在字典中,还可以指定要使用的默认值。...,直到计算机内存耗尽为止。
原理: 将原始数组切分成较小的数组,直到每个小数组只有一个位置,接着将小数组归并成较大的数组,直到最后只有一个排序完毕的大数组。...partition函数返回值将赋值给index if (left < index - 1) { //如果子数组存在较小值的元素 quick(array, left...把数组当作二叉树来排序而得名 1.索引0是树的根节点; 2.除根节点外,任意节点N的父节点是N/2; 3.节点L的左子节点是2*L; 4.节点R的右子节点是2*R+1 数组[3, 5, 1, 6, 4...,或是true,又或是搜索项的索引 } } return -1; //没有找到该项,则返回-1 表示该索引不存在 }; 搜索算法-二分搜索 游戏示例:一个1到100的数字游戏。...array.length; i++) { console.log(array[i]); } }; printArray([1, 2, 3, 4, 5]); 函数式编程:(重点是需要描述什么,而不是如何描述
元组中的每个值都有一个指定的索引值。...值得注意的是,python是一种基于零索引的语言。所有这些意味着元组中的第一个值是索引0。...对于下面的示例代码,它将返回一个元组,其中包含索引0的对象,而不包括索引2的对象。...元组是不可变的,而列表是可变的。以下是元组列表的一些其他优点 组比列表更快。如果你要定义一组常量值,那么你将要做的就是迭代它,使用元组而不是列表。...根据定义,Fibonacci序列中的前两个数字是1和1,或0和1,具体取决于所选择的序列起点,以及每个后续数字是前两个数字的总和。
应用 应用添加了一个新级别的包装,而不是将函数应用于包装对象,函数也被包装。在下面的代码中,函数被包装在一个可选的。...最重要的是: BiConsumer:一种使用两个输入参数而不返回结果的操作,通常用在forEach映射方法中。支持使用andThen方法链接BiConsumers。...:应用谓词过滤输入。 map(..):通过应用函数来转换输入。 flatMap(..):使用基于映射函数的流中的值替换输入。 distinct():使用Object.equals()返回不同的值。...为了加速调用,我们可以缓存输出,对于给定的输入,只返回缓存结果,而不是实际计算结果。 意图 其目的是缓存给定输入的函数结果,并使用它加速对给定相同输入的相同函数的进一步调用。...示例 在下面的示例中,我们将重用 Fibonacci 代码并添加 Guava 缓存。缓存将保存 Fibonacci 的返回值,而键是输入数字。
因为我们缺少了停止条件,即何时 recursive 函数可以获得返回值,而不是继续调用自身。...当 count 值为 120 的时候,停止调用自身,并返回 story。最后我们得到了 121 个 story 字符串相加的结果。...而 Python 也对递归层数有所限制,并且不支持尾递归优化。 但是使用递归可以快速解决问题,尤其是一些对资源要求不是很大的问题。递归也可以帮我们梳理思路,然后再使用循环重写递归。...快速排序使用“分而治之”的方法。对于一串序列,首先从中选取一个数,凡是小于这个数的值就被放在左边一摞,凡是大于这个数的值就被放在右边一摞。然后,继续对左右两摞进行快速排序。...直到进行快速排序的序列长度小于 2 (即序列中只有一个值或者空值)。 注意:递归版的快排比较消耗资源。
函数式编程是什么 函数式编程更加强调程序执行的结果而非执行的过程,倡导利用若干简单的执行单元让计算结果不断渐进,逐层推导复杂的运算,而不是设计一个复杂的执行过程。...我们可以假设U为可证,那么可以推出PM是矛盾(不相容)的;但是假设U不可证,却推导不出PM是矛盾的。U的含义是在PM中不可证,而事实上,它被证明不可证,所以U是PM中不可证的真命题。...和ML都是不纯的编程语言,但是Haskell是side effect free的 函数是一等公民 函数是一等公民,指的是你可以将函数作为参数、返回值、数据结构存在,而且不仅可以用函数名引用,甚至可以匿名调用...作为返回值 (defn add [num] (fn [other-num] (+ num other-num))) ;; as return-value (def add-one (add 1...纯函数还具有引用透明性的特点,也就是同样的输入导致同样的输出,以至于完全可以用函数的值代替对函数的调用。
代码计算了由left和right索引定义的范围的中间索引(存储在mid中)。起初,这个范围是整个项目列表的长度。如果mid索引处的值与needle相同,则返回mid。...i和j索引从索引0开始,即范围的左端。在每一步中,索引j总是向右移动。只有当索引j处的值小于或等于枢纽值时,索引i才会移动。...因此,i索引左侧的所有值都小于或等于枢轴,而i索引右侧的所有值都大于枢轴。 整个过程会重复进行,我们会在左右分区上递归调用quicksort()。...在合并阶段中重复执行此操作,直到最终结果是原始的mergeSort()调用以排序顺序返回完整列表。 图 5-4:合并步骤比较较小排序列表开头的两个值,并将它们移动到较大的排序列表中。...这个函数调用,反过来返回isOdd(40)的相反布尔值,依此类推,直到isOdd(0)返回False。递归函数调用的数量决定了在最终返回值返回之前作用于返回值的not运算符的数量。
Haskell 中的 fibonacci 数列: fibonacci = 1 : 1 : zipWith (+) fibonacci (tail fibonacci) 这里 fibonacci 本身是一个惰性结构...惰性列表的使用增加了我们编程的表达能力,让我们可以更关注数据结构本身的特性,而不是浪费时间在如何去管理堆栈上面。...这并不是我们期待的行为,这里需要让这个 fetch 的动作在我们需要的时候才去执行,而不是声明的时候就开始执行的话,通常的做法是把它改成下面的样子。...for...of...、 ...itor 以及 Array.from 来访问,当next方法的返回值中done为true时,迭代结束。...另外,需要特别说明的是,虽然这篇文章通篇是在讲惰性列表,但是惰性列表并不是银弹,相反的,惰性结构的滥用会在程序的执行过程中缓存大量的thunk,增大在内存上的开销。
当函数在一直递推,直到遇到墙后返回,这个墙就是结束条件。...所以递归要有两个要素,结束条件与递推关系 注: 递归的时候,每次调用一个函数,计算机都会为这个函数分配新的空间,这就是说,当被调函数返回的时候,调用函数中的变量依然会保持原先的值,否则也不可能实现反向输出...、返回值、返回点以及子程序(函数)的局部变量。...用户栈 是用户进程空间中的一块区域,用于保存用户进程的子程序间相互调用的参数、返回值、返回点以及子程序(函数)的局部变量。 我们编写的递归程序属于用户程序,因此使用的是用户栈。...而递归调用,只有走到最后的结束点后函数才能依次退出,而未到达最后的结束点之前,占用的栈空间一直没有释放,如果递归调用次数过多,就可能导致占用的栈资源超过线程的最大值,从而导致栈溢出,导致程序的异常退出。
从本质上讲,该模块包含许多快速且内存效率高的方法,这些方法可以帮助我们用纯Python简洁而高效地构建应用程序。 无限迭代器 如果我们想构造一个返回无限均匀间隔值的迭代器呢?...终止迭代器 在本节中,我将说明终止迭代的强大特性。这些函数可以用于许多场景,例如: 我们可能有很多迭代,我们想在一个序列中一个一个地对所有迭代的元素执行一个操作。...Chain 这个方法允许我们创建一个迭代器,它返回序列中所有输入迭代中的元素,直到没有元素剩下为止。因此,它可以将连续序列视为单个序列。...该函数返回一个键、值对的迭代器,其中键是组键,值是按键分组的连续元素的集合。...输出也是一个迭代器,它返回给定数量的项的可迭代值。
对应上面的问题,取前3个元素,用一行代码就可以完成切片: >>> L[0:3] ['Michael', 'Sarah', 'Tracy'] L[0:3]表示,从索引0开始取,直到索引3为止,但不包括索引...而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。...如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中: >>> g = fib(6) >>> while True: ......这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。...可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。
,直到内存溢出。...F(n) = F(n-1) + F(n-2) 即从第三个数字开始,对应的数值是前面两个数字的和,其中 n 表示数字在斐波那契数列中的序号,最后一个公式就是递归模型,通过这个公式就可以把求解斐波那契数列的问题拆分为多个子问题来处理...:即把求解 F(n) 的值拆分为求解 F(n-1) 和 F(n-2) 两个子问题返回值的和,依次类推,直到到达终止条件:当 n=2 时,返回数值 1,当 n=1 时,返回数值 0。...num return num } 这一次,我们会通过预定义数组 fibs 保存已经计算过的斐波那契序号对应的数值(序号 n 与对应数组索引的映射关系为 n-1,因为数组索引从下标 0 开始,而这里的斐波那契序号从...1 开始),这样下次要获取对应序号的斐波那契值时会直接返回而不是调用一次递归函数进行计算。
在Python编程中,生成器(Generator)是一个强大而又灵活的工具,它允许您在需要的时候生成一系列的值,而不必一次性将它们全部存储在内存中。...它们以一种惰性(lazy)的方式生成值,逐个产生并返回,而不是一次性生成一个大的序列。这意味着生成器在处理大型数据集时非常高效,因为它们不需要占用大量内存。...生成器最常见的形式是使用函数定义,其中包含一个或多个yield语句。当函数执行到yield语句时,它会产生一个值并暂停执行,将值返回给调用者。...这就是生成器的工作原理:每次调用next(),它会执行生成器函数直到遇到下一个yield语句,然后返回产生的值。生成器会保持状态,以便下一次调用可以继续执行。3....结论生成器是Python中强大且高效的工具,用于惰性生成序列数据。它们通过yield语句实现值的逐个产生和返回,避免了内存浪费。本文深入解释了生成器是什么以及它们的工作原理,同时提供了实际应用示例。
根据字典中的值排序 方法一:利用zip把字典转换为元组(值在前,键在后),然后sorted排序。 ? 方法二: 利用sorted的key参数。...因为 items() 返回的是一个 list,list 在迭代的时候会预先把所有的元素加载到内存,而 iteritem() 返回的一个迭代器(iterators),迭代器在迭代的时候,迭代元素逐个的生成...这就是我们通常意义上面所认识的函数(或者说是子程序),但有时候我们需要创建某个函数,它并不简单的返回一个值, 而是可以不断的释放一个值的序列。那么这个特殊的函数就需要能够“保存”它的状态。...在Python中,有这种能力的“函数”被称为生成器,它们相当有用。生成器(yield语句)刚开始被引入进来主要是用来方便的生成序列值。 迭代器切片操作 ? 迭代器迭代多个对象 ?...,装饰器的返回值也是一个函数对象。
你会翻开封面,把书名和作者的名字一一告诉他,还是开始凭记忆回答?哪个能节省你更多的时间? 发现其中的相似之处了吗?使用记忆法,当函数提供输入时,它执行所需的计算并在返回值之前将结果存储到缓存中。...缓存是怎么工作的 JavaScript 中的缓存的概念主要建立在两个概念之上,它们分别是: 闭包 高阶函数(返回函数的函数) 闭包 闭包是函数和声明该函数的词法环境的组合。 不是很清楚?...n 元素,其中的序列是: [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, …] 知道每个值都是前两个值的和,这个问题的递归解是: function fibonacci...请注意,当 n 的值到终止递归之前,需要做大量的工作和时间,因为序列中存在对某些值的重复求值。...对于具有有限且高度重复输入范围的函数。 用于具有重复输入值的递归函数。 对于纯函数,即每次使用特定输入调用时返回相同输出的函数。
领取专属 10元无门槛券
手把手带您无忧上云