Python 化 JavaScript
Python 拥有许多强大的实用函数,例如 range
、enumerate
、zip
等,这些函数基于可迭代对象和迭代器协议构建。结合生成器函数,这些协议自 2016 年左右起就在所有 Evergreen 浏览器和 Node.js 中可用,但在我看来,它们的使用率却低得令人吃惊。在这篇文章中,我将使用 TypeScript 实现其中一些辅助函数,希望能改变这种现状。
迭代器、可迭代对象和生成器函数
迭代器协议
迭代器协议是一种生成值序列的标准方法。要使一个对象成为迭代器,它必须通过实现 next
方法来遵守迭代器协议,例如:
const iterator = { i: 0, next() { return { done: false, value: this.i++ }; } };
然后,我们可以重复调用 next
方法来获取值:
console.log(iterator.next().value); // → 0 console.log(iterator.next().value); // → 1 console.log(iterator.next().value); // → 2 console.log(iterator.next().value); // → 3 console.log(iterator.next().value); // → 4
next
方法应该返回一个对象,该对象包含一个 value
属性(包含实际值)和一个 done
属性(指定迭代器是否已耗尽,即是否无法再生成值)。根据 MDN 的说法,这两个属性都不是严格必需的,如果两者都缺失,则返回值被视为 { done: false, value: undefined }
。
可迭代对象协议
可迭代对象协议允许对象定义其自身的迭代行为。要遵守可迭代对象协议,对象必须使用 Symbol.iterator
键定义一个方法,该方法返回一个迭代器。许多内置对象(如 Array
、TypedArray
、Set
和 Map
)都实现了此协议,因此可以使用 for...of
循环对其进行迭代。
例如,对于数组,values
方法被指定为数组的 Symbol.iterator
方法:
console.log(Array.prototype.values === Array.prototype[Symbol.iterator]); // → true
我们可以结合迭代器和可迭代对象协议来创建一个可迭代的迭代器,如下所示:
const iterable = { i: 0, [Symbol.iterator]() { const iterable = this; return { next() { return { done: false, value: iterable.i++ }; } }; } };
这两个协议的名称不幸地非常相似,至今仍然让我感到困惑。
正如您可能猜到的那样,我们的迭代器和可迭代对象示例是无限的,这意味着它们可以永远生成值。这是一个非常强大的特性,但也容易成为一个陷阱。例如,如果我们要在一个 for...of
循环中使用可迭代对象,则循环将永远持续下去;或者用作 Array.from
的参数,JS 最终会抛出一个 RangeError
,因为数组会变得太大:
// 将无限循环: for (const value of iterable) { console.log(value); } // 将抛出 RangeError const arr = Array.from(iterable);
迭代器和可迭代对象甚至可以无限的原因是它们是惰性求值的,即只有在使用时才会生成值。
生成器函数
虽然迭代器和可迭代对象是宝贵的工具,但编写起来有点麻烦。作为替代方案,引入了生成器函数。
生成器函数使用 function*
(或 function *
,星号可以在 function
关键字和函数名称之间任意位置)指定,允许我们中断函数的执行,使用 yield
关键字返回值,并在稍后继续中断的地方继续执行,同时保持其内部状态:
const iterator = { i: 0, next() { return { done: false, value: this.i++ }; } };
Python 实用程序
如引言中所述,Python 有一些非常有用的内置实用程序,它们基于上述协议。JavaScript 最近也为迭代器增加了一些辅助方法,例如 .drop()
和 .filter()
,但(也许还没有)拥有 Python 中一些更有趣的实用程序。
让我们动手实践!
现在理论部分已经结束,让我们开始实现一些 Python 函数吧!
注意:此处显示的这些实现都不应按原样用于生产环境。 它们缺乏错误处理和边界条件检查。
enumerate(iterable [,start])
Python 中的 enumerate
为输入序列或可迭代对象中的每个项目返回一系列元组,其中第一个位置包含计数,第二个位置包含项目:
console.log(iterator.next().value); // → 0 console.log(iterator.next().value); // → 1 console.log(iterator.next().value); // → 2 console.log(iterator.next().value); // → 3 console.log(iterator.next().value); // → 4
enumerate
还接受一个可选的 start
参数,指示计数器应从何处开始:
console.log(Array.prototype.values === Array.prototype[Symbol.iterator]); // → true
让我们使用生成器函数在 TypeScript 中实现它。我们可以使用 python 文档中概述的实现作为指导
const iterable = { i: 0, [Symbol.iterator]() { const iterable = this; return { next() { return { done: false, value: iterable.i++ }; } }; } };
由于 JavaScript 中的字符串实现了可迭代对象协议,我们可以简单地将字符串传递给我们的 enumerate
函数并像这样调用它:
// 将无限循环: for (const value of iterable) { console.log(value); } // 将抛出 RangeError const arr = Array.from(iterable);
repeat(elem [,n])
repeat
是内置 itertools
库的一部分,它重复给定的输入 elem
n 次,如果未指定 n,则无限重复。我们再次可以将 python 文档中的实现作为起点。
function* sequence() { let i = 0; while (true) { yield i++; } } const seq = sequence(); console.log(seq.next().value); // → 0; console.log(seq.next().value); // → 1; console.log(seq.next().value); // → 2; // 将无限循环,从 3 开始 for (const value of seq) { console.log(value); }
(此处省略了 cycle
、range
函数的实现,因为篇幅过长,但其逻辑与原文相同,只是将代码用 TypeScript 重写)
结论
这是我的第一篇博客文章,我希望您觉得它有趣,并且也许您会在未来的项目中使用迭代器、可迭代对象和生成器。如果您有任何疑问或需要澄清,请留下评论,我很乐意提供更多信息。
需要注意的是,与使用计数器的原始 for
循环相比,性能相差甚远。这在许多情况下可能无关紧要,但在高性能场景中绝对很重要。当我将 PCM 数据绘制到画布上并使用迭代器和生成器时,发现帧丢失了,这让我很苦恼。事后看来这可能是显而易见的,但当时对我来说却并非如此 :D
干杯!
以上是Python 化 JavaScript的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

Python在游戏和GUI开发中表现出色。1)游戏开发使用Pygame,提供绘图、音频等功能,适合创建2D游戏。2)GUI开发可选择Tkinter或PyQt,Tkinter简单易用,PyQt功能丰富,适合专业开发。

Python更易学且易用,C 则更强大但复杂。1.Python语法简洁,适合初学者,动态类型和自动内存管理使其易用,但可能导致运行时错误。2.C 提供低级控制和高级特性,适合高性能应用,但学习门槛高,需手动管理内存和类型安全。

要在有限的时间内最大化学习Python的效率,可以使用Python的datetime、time和schedule模块。1.datetime模块用于记录和规划学习时间。2.time模块帮助设置学习和休息时间。3.schedule模块自动化安排每周学习任务。

Python在开发效率上优于C ,但C 在执行性能上更高。1.Python的简洁语法和丰富库提高开发效率。2.C 的编译型特性和硬件控制提升执行性能。选择时需根据项目需求权衡开发速度与执行效率。

pythonlistsarepartofthestAndArdLibrary,herilearRaysarenot.listsarebuilt-In,多功能,和Rused ForStoringCollections,而EasaraySaraySaraySaraysaraySaraySaraysaraySaraysarrayModuleandleandleandlesscommonlyusedDduetolimitedFunctionalityFunctionalityFunctionality。

Python在自动化、脚本编写和任务管理中表现出色。1)自动化:通过标准库如os、shutil实现文件备份。2)脚本编写:使用psutil库监控系统资源。3)任务管理:利用schedule库调度任务。Python的易用性和丰富库支持使其在这些领域中成为首选工具。

每天学习Python两个小时是否足够?这取决于你的目标和学习方法。1)制定清晰的学习计划,2)选择合适的学习资源和方法,3)动手实践和复习巩固,可以在这段时间内逐步掌握Python的基本知识和高级功能。

Python和C 各有优势,选择应基于项目需求。1)Python适合快速开发和数据处理,因其简洁语法和动态类型。2)C 适用于高性能和系统编程,因其静态类型和手动内存管理。
