Dart【06】generator生成器函数

2024-08-20 21:28

本文主要是介绍Dart【06】generator生成器函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

什么是生成器函数

Dart生成器函数 (generator) 可以渐进的返回一个值的序列。

Dart内置了两种生成器函数的支持:

同步生成器(sync*):返回一个Iterable对象。
异步生成器(async*):返回一个Stream对象。

同步生成器

使用同步生成器修饰的函数返回的是迭代器Iterable

Iterable主要使用iterator的两个方法moveNext()currentcurrent代表了当前元素,moveNext()将迭代器推进到迭代的下一个元素。

用一段代码展示如何使用同步生成器:

Iterable<int> naturalsTo(int n) sync* {int k = 0;while (k < n) yield k++;
}

测试代码:

void main() {Iterable<int> sequence = naturalsTo(5);print("Starting...");for (int value in sequence) {print(value);}print("DONE");
}

输出如下:

Starting…
0
1
2
3
4
DONE

代码解读:

上面示例中的naturalsTo函数就是使用同步生成器修饰的函数,首先在函数方法体花括号前加入sync*关键字,然后使用yield关键字进行值的返回。

上面的代码示例yield关键字向迭代器序列依次添加了五个值。

看到这里你可能有点疑问,函数返回值不是return吗?yield是干嘛的?

yield和yield*

yield的作用:

yield向周围sync*函数的迭代器中添加一个值。就像return,但不会终止函数。

上面的代码示例yield关键字向迭代器序列依次添加了五个值。

yield功能类似的还有一个关键字yield*yield*只是一种简化写法。如果生成器是递归的,可以使用 yield* 来提高其性能。

用两段代码示例来展示yield*是如何简化代码的:

这是一段没有使用yield*的代码:

void main() {for (int i in numbersDownFrom(3)) {print('$i');}
}Iterable<int> numbersDownFrom(int n) sync* {if (n != 0) {yield n;for (var val in numbersDownFrom(n - 1)) {yield val;}}
}

输出如下:

3
2
1

 for (var val in numbersDownFrom(n - 1)) {yield val;}

这段代码是函数的递归调用,代码流程完全是同步的,你可能要花上一点时间阅读一下代码,你就能理解这段代码做了什么事情。

接下来我们用yield*来简化这段代码:

void main() {for (int i in numbersDownFrom(3)) {print('$i');}
}Iterable<int> numbersDownFrom(int n) sync* {if (n != 0) {yield n;yield* numbersDownFrom(n - 1);}
}

输出如下:

3
2
1

两段代码的作用完全一样,你应该已经理解yield*的作用了,就是对For循环+yield的一种简化。

异步生成器

异步生成器async*在原理上和同步生成器完全一样,都是渐进的返回一个值的序列,唯一区别就是同步生成器返回的是迭代器。异步声明器返回的是Stream

关于Stream的详细介绍参考作者之前的文章。

用一段与上面sync*使用方式一样的代码来为你展示如何使用异步生成器async*

Stream<int> naturalsTo(int n) async* {int k = 0;while (k < n) yield k++;
}

测试代码:

void main() async{Stream<int> sequence = naturalsTo(5);print("Starting...");await for (int value in sequence) {print(value);}print("DONE");
}

输出如下:

Starting…
0
1
2
3
4
DONE

async*sync*工作原理完全一致,如果你对asyncawait for有疑问,参考作者之前的文章。

sync,sync*,async,async*

文章看到这里对异步的全部介绍已经结束了,用一张图片来帮助你记忆sync,sync*,async,async*的区别。

这篇关于Dart【06】generator生成器函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1091219

相关文章

Python中的filter() 函数的工作原理及应用技巧

《Python中的filter()函数的工作原理及应用技巧》Python的filter()函数用于筛选序列元素,返回迭代器,适合函数式编程,相比列表推导式,内存更优,尤其适用于大数据集,结合lamb... 目录前言一、基本概念基本语法二、使用方式1. 使用 lambda 函数2. 使用普通函数3. 使用 N

MySQL中REPLACE函数与语句举例详解

《MySQL中REPLACE函数与语句举例详解》在MySQL中REPLACE函数是一个用于处理字符串的强大工具,它的主要功能是替换字符串中的某些子字符串,:本文主要介绍MySQL中REPLACE函... 目录一、REPLACE()函数语法:参数说明:功能说明:示例:二、REPLACE INTO语句语法:参数

python中update()函数的用法和一些例子

《python中update()函数的用法和一些例子》update()方法是字典对象的方法,用于将一个字典中的键值对更新到另一个字典中,:本文主要介绍python中update()函数的用法和一些... 目录前言用法注意事项示例示例 1: 使用另一个字典来更新示例 2: 使用可迭代对象来更新示例 3: 使用

Python lambda函数(匿名函数)、参数类型与递归全解析

《Pythonlambda函数(匿名函数)、参数类型与递归全解析》本文详解Python中lambda匿名函数、灵活参数类型和递归函数三大进阶特性,分别介绍其定义、应用场景及注意事项,助力编写简洁高效... 目录一、lambda 匿名函数:简洁的单行函数1. lambda 的定义与基本用法2. lambda

Python 函数详解:从基础语法到高级使用技巧

《Python函数详解:从基础语法到高级使用技巧》本文基于实例代码,全面讲解Python函数的定义、参数传递、变量作用域及类型标注等知识点,帮助初学者快速掌握函数的使用技巧,感兴趣的朋友跟随小编一起... 目录一、函数的基本概念与作用二、函数的定义与调用1. 无参函数2. 带参函数3. 带返回值的函数4.

MySQL中DATE_FORMAT时间函数的使用小结

《MySQL中DATE_FORMAT时间函数的使用小结》本文主要介绍了MySQL中DATE_FORMAT时间函数的使用小结,用于格式化日期/时间字段,可提取年月、统计月份数据、精确到天,对大家的学习或... 目录前言DATE_FORMAT时间函数总结前言mysql可以使用DATE_FORMAT获取日期字段

Django中的函数视图和类视图以及路由的定义方式

《Django中的函数视图和类视图以及路由的定义方式》Django视图分函数视图和类视图,前者用函数处理请求,后者继承View类定义方法,路由使用path()、re_path()或url(),通过in... 目录函数视图类视图路由总路由函数视图的路由类视图定义路由总结Django允许接收的请求方法http

MySQL常用字符串函数示例和场景介绍

《MySQL常用字符串函数示例和场景介绍》MySQL提供了丰富的字符串函数帮助我们高效地对字符串进行处理、转换和分析,本文我将全面且深入地介绍MySQL常用的字符串函数,并结合具体示例和场景,帮你熟练... 目录一、字符串函数概述1.1 字符串函数的作用1.2 字符串函数分类二、字符串长度与统计函数2.1

使用Python构建智能BAT文件生成器的完美解决方案

《使用Python构建智能BAT文件生成器的完美解决方案》这篇文章主要为大家详细介绍了如何使用wxPython构建一个智能的BAT文件生成器,它不仅能够为Python脚本生成启动脚本,还提供了完整的文... 目录引言运行效果图项目背景与需求分析核心需求技术选型核心功能实现1. 数据库设计2. 界面布局设计3

python使用try函数详解

《python使用try函数详解》Pythontry语句用于异常处理,支持捕获特定/多种异常、else/final子句确保资源释放,结合with语句自动清理,可自定义异常及嵌套结构,灵活应对错误场景... 目录try 函数的基本语法捕获特定异常捕获多个异常使用 else 子句使用 finally 子句捕获所