- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章一篇文章彻底搞懂Python中可迭代(Iterable)、迭代器(Iterator)与生成器(Generator)的概念由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
前言 。
在python中可迭代(iterable)、迭代器(iterator)和生成器(generator)这几个概念是经常用到的,初学时对这几个概念也是经常混淆,现在是时候把这几个概念搞清楚了.
0x00 可迭代(iterable) 。
简单的说,一个对象(在python里面一切都是对象)只要实现了只要实现了__iter__()方法,那么用isinstance()函数检查就是iterable对象; 。
例如 。
1
2
3
4
5
6
7
8
|
class
iterobj:
def
__iter__(
self
):
# 这里简单地返回自身
# 但实际情况可能不会这么写
# 而是通过内置的可迭代对象来实现
# 下文的列子中将会展示
return
self
|
上面定义了一个类iterobj并实现了__iter__()方法,这个就是一个可迭代(iterable)对象 。
1
2
3
4
|
it
=
iterobj()
print
(
isinstance
(it, iterable))
# true
print
(
isinstance
(it, iterator))
# false
print
(
isinstance
(it, generator))
# false
|
记住这个类,下文我们还会看到这个类的定义.
常见的可迭代对象 。
在python中有哪些常见的可迭代对象呢?
关于第1、2点我们可以通过以下来验证 。
1
2
3
4
5
6
7
8
9
|
print
(
isinstance
([], iterable))
# true list 是可迭代的
print
(
isinstance
({}, iterable))
# true 字典是可迭代的
print
(
isinstance
((), iterable))
# true 元组是可迭代的
print
(
isinstance
(
set
(), iterable))
# true set是可迭代的
print
(
isinstance
('', iterable))
# true 字符串是可迭代的
currpath
=
os.path.dirname(os.path.abspath(__file__))
with
open
(currpath
+
'/model.py'
) as
file
:
print
(
isinstance
(
file
, iterable))
# true
|
我们再来看第3点, 。
1
2
3
4
|
print
(
hasattr
([],
"__iter__"
))
# true
print
(
hasattr
({},
"__iter__"
))
# true
print
(
hasattr
((),
"__iter__"
))
# true
print
(
hasattr
('',
"__iter__"
))
# true
|
这些内置集合或序列对象都有__iter__属性,即他们都实现了同名方法。但这个可迭代对象要在for循环中被使用,那么它就应该能够被内置的iter()函数调用并转化成iterator对象.
例如,我们看内置的可迭代对象 。
1
2
3
4
|
print
(
iter
([]))
# <list_iterator object at 0x110243f28>
print
(
iter
({}))
# <dict_keyiterator object at 0x110234408>
print
(
iter
(()))
# <tuple_iterator object at 0x110243f28>
print
(
iter
(''))
# <str_iterator object at 0x110243f28>
|
它们都相应的转成了对应的迭代器(iterator)对象.
现在回过头再看看一开始定义的那个iterobj类 。
1
2
3
4
5
6
7
|
class
iterobj:
def
__iter__(
self
):
return
self
it
=
iterobj()
print
(
iter
(it))
|
我们使用了iter()函数,这时候将再控制台上打印出以下信息:
traceback (most recent call last): file "/users/mac/pycharmprojects/iterable_iterator_generator.py", line 71, in <module> print(iter(it)) typeerror: iter() returned non-iterator of type 'iterobj' 。
出现了类型错误,意思是iter()函数不能将‘非迭代器'类型转成迭代器.
那如何才能将一个可迭代(iterable)对象转成迭代器(iterator)对象呢?
我们修改一下iterobj类的定义 。
1
2
3
4
5
6
7
|
class
iterobj:
def
__init__(
self
):
self
.a
=
[
3
,
5
,
7
,
11
,
13
,
17
,
19
]
def
__iter__(
self
):
return
iter
(
self
.a)
|
我们在构造方法中定义了一个名为a的列表,然后还实现了__iter__()方法.
修改后的类是可以被iter()函数调用的,即也可以在for循环中使用 。
1
2
3
4
5
6
7
|
it
=
iterobj()
print
(
isinstance
(it, iterable))
# true
print
(
isinstance
(it, iterator))
# false
print
(
isinstance
(it, generator))
# false
print
(
iter
(it))
# <list_iterator object at 0x102007278>
for
i
in
it:
print
(i)
# 将打印3、5、7、11、13、17、19元素
|
因此在定义一个可迭代对象时,我们要非常注意__iter__()方法的内部实现逻辑,一般情况下,是通过一些已知的可迭代对象(例如,上文提到的集合、序列、文件等或其他正确定义的可迭代对象)来辅助我们来实现 。
关于第4点说明的意思是iter()函数可以将一个实现了__getitem__()方法的对象转成迭代器对象,也可以在for循环中使用,但是如果用isinstance()方法来检测时,它不是一个可迭代对象.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class
iterobj:
def
__init__(
self
):
self
.a
=
[
3
,
5
,
7
,
11
,
13
,
17
,
19
]
def
__getitem__(
self
, i):
return
self
.a[i]
it
=
iterobj()
print
(
isinstance
(it, iterable))
# false
print
(
isinstance
(it, iterator))
# false
print
(
isinstance
(it, generator)) false
print
(
hasattr
(it,
"__iter__"
))
# false
print
(
iter
(it))
# <iterator object at 0x10b231278>
for
i
in
it:
print
(i)
# 将打印出3、5、7、11、13、17、19
|
这个例子说明了可以在for中使用的对象,不一定是可迭代对象.
现在我们做个小结:
0x01 迭代器(iterator) 。
上文很多地方都提到了iterator,现在我们把这个坑填上.
当我们对可迭代的概念了解后,对于迭代器就比较好理解了.
一个对象实现了__iter__()和__next__()方法,那么它就是一个迭代器对象。 例如 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class
iterobj:
def
__init__(
self
):
self
.a
=
[
3
,
5
,
7
,
11
,
13
,
17
,
19
]
self
.n
=
len
(
self
.a)
self
.i
=
0
def
__iter__(
self
):
return
iter
(
self
.a)
def
__next__(
self
):
while
self
.i <
self
.n:
v
=
self
.a[
self
.i]
self
.i
+
=
1
return
v
else
:
self
.i
=
0
raise
stopiteration()
|
在iterobj中,构造函数中定义了一个列表a,列表长度n,索引i.
1
2
3
4
5
6
|
it
=
iterobj()
print
(
isinstance
(it, iterable))
# true
print
(
isinstance
(it, iterator))
# true
print
(
isinstance
(it, generator))
# false
print
(
hasattr
(it,
"__iter__"
))
# true
print
(
hasattr
(it,
"__next__"
))
# true
|
我们可以发现上文提到的 。
集合和序列对象是可迭代的但不是迭代器 。
1
2
3
4
5
|
print
(
isinstance
([], iterator))
# false
print
(
isinstance
({}, iterator))
# false
print
(
isinstance
((), iterator))
# false
print
(
isinstance
(
set
(), iterator))
# false
print
(
isinstance
('', iterator))
# false
|
而文件对象是迭代器 。
1
2
3
|
currpath
=
os.path.dirname(os.path.abspath(__file__))
with
open
(currpath
+
'/model.py'
) as
file
:
print
(
isinstance
(
file
, iterator))
# true
|
一个迭代器(iterator)对象不仅可以在for循环中使用,还可以通过内置函数next()函数进行调用。 例如 。
1
2
3
|
it
=
iterobj()
next
(it)
# 3
next
(it)
# 5
|
0x02 生成器(generator) 。
现在我们来看看什么是生成器?
一个生成器既是可迭代的也是迭代器 。
定义生成器有两种方式:
先看第1种情况 。
1
2
3
4
5
6
7
8
|
g
=
(x
*
2
for
x
in
range
(
10
))
# 0~18的偶数生成器
print
(
isinstance
(g, iterable))
# true
print
(
isinstance
(g, iterator))
# true
print
(
isinstance
(g, generator))
# true
print
(
hasattr
(g,
"__iter__"
))
# true
print
(
hasattr
(g,
"__next__"
))
# true
print
(
next
(g))
# 0
print
(
next
(g))
# 2
|
列表生成器可以不需要消耗大量的内存来生成一个巨大的列表,只有在需要数据的时候才会进行计算.
再看第2种情况 。
1
2
3
|
def
gen():
for
i
in
range
(
10
):
yield
i
|
这里yield的作用就相当于return,这个函数就是顺序地返回[0,10)的之间的自然数,可以通过next()或使用for循环来遍历.
当程序遇到yield关键字时,这个生成器函数就返回了,直到再次执行了next()函数,它就会从上次函数返回的执行点继续执行,即yield退出时保存了函数执行的位置、变量等信息,再次执行时,就从这个yield退出的地方继续往下执行.
在python中利用生成器的这些特点可以实现协程。协程可以理解为一个轻量级的线程,它相对于线程处理高并发场景有很多优势.
看下面一个用协程实现的生产者-消费者模型 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
def
producer(c):
n
=
0
while
n <
5
:
n
+
=
1
print
(
'producer {}'
.
format
(n))
r
=
c.send(n)
print
(
'consumer return {}'
.
format
(r))
def
consumer():
r
=
''
while
true:
n
=
yield
r
if
not
n:
return
print
(
'consumer {} '
.
format
(n))
r
=
'ok'
if
__name__
=
=
'__main__'
:
c
=
consumer()
next
(c)
# 启动consumer
producer(c)
|
这段代码执行效果如下 。
producer 1 consumer 1 producer return ok producer 2 consumer 2 producer return ok producer 3 consumer 3 producer return ok 。
协程实现了cpu在两个函数之间进行切换从而实现并发的效果.
0x04 引用 。
docs.python.org/3.7/ 。
总结 。
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我的支持.
原文链接:https://juejin.im/post/5ccafbf5e51d453a3a0acb42 。
最后此篇关于一篇文章彻底搞懂Python中可迭代(Iterable)、迭代器(Iterator)与生成器(Generator)的概念的文章就讲到这里了,如果你想了解更多关于一篇文章彻底搞懂Python中可迭代(Iterable)、迭代器(Iterator)与生成器(Generator)的概念的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在尝试表达以下内容: 给定一个矩阵和两个索引增量,返回矩阵中所有数字的四倍体:沿行,列或对角线的四倍体。 use std::iter::Iterator; use std::iter::Peeka
假设我们有以下类组成角色 Iterable : class Word-Char does Iterable { has @.words; method !pairize($item)
我编写了一个 ADT 排序二叉树,其功能如下: public Iterator getInorderIterator(){ return new InorderIterator(); } 有效
在包装(内部)迭代器时,通常必须将 __iter__ 方法重新路由到底层可迭代对象。考虑以下示例: class FancyNewClass(collections.Iterable): def
尽管如此,我遍历了以下 NSSet , NSMutableArray , NSFastEnumeration文档,我找不到下面提到的场景的令人满意的来源: 此处,NSMutableArray、NSAr
我发现在 Python 中 collections.Iterable 和 typing.Iterable 都可以用于类型注释和检查对象是否可迭代,即 >isinstance(obj, collecti
我想拆分实现 Iterator 的对象的输出分为两个实现 Iterator 的对象和 Iterator .由于其中一个输出的迭代次数可能比另一个多,因此我需要缓冲 Iterator 的输出。 (因为我
我正在尝试用 Rust 编写一个简单的迭代器: #[derive(Debug)] pub struct StackVec { storage: &'a mut [T], len: us
什么意思: Separator.Iterator.Element == Self.Iterator.Element.Iterator.Element 在this (Swift 标准库)swift 实例
调用 anIterable.iterator() 会返回新的迭代器还是现有的迭代器?它依赖于 Iterable 的实现吗? 更具体地说,以下代码是否按预期工作(即内部循环将从头开始迭代)? for (
我正在尝试转换 &str 的矢量对成一个 HashMap使用以下代码片段: use std::collections::HashMap; fn main() { let pairs = vec!(
这将使安全地迭代同一元素两次成为可能,或者为在项目类型中迭代的全局事物保持某种状态。 类似于: trait IterShort where Self: Borrow, { type I
我在 String 的字符上使用迭代器: pub fn is_yelling(message: &str) -> bool { let letters = message.chars().fi
这将使安全地迭代同一元素两次成为可能,或者为在项目类型中迭代的全局事物保持某种状态。 类似于: trait IterShort where Self: Borrow, { type I
要在 Rust 中实现迭代器,我们只需要实现 next 方法,如 in the documentation 所解释的那样.但是,Iterator 特征 has many more methods .
我正在为多个结构实现 Iterator 特性并遇到了一些问题。为什么为 Rows 实现 Iterator 显示错误?这是一个链接:link to playground 基本上为什么这不起作用? str
我将集合转储到磁盘上。当请求时,应该检索这些集合(没问题)和 iterator应该为它构建返回对检索到的值的引用。 iterator之后被丢弃了,我不再需要收藏了。我也希望它被删除。 到目前为止我尝试
我正在尝试为实现特征的结构实现默认迭代器。我的特征称为 DataRow,代表一行表格单元格,如下所示: pub trait DataRow { // Gets a cell by index
Rust 中是否有提供 iter() 的 Trait方法?我只找到了特征 IntoIterator ,供应into_iter() . 这里要明确一点:我不想要 Iterator特性,提供 next()
我想在迭代器上定义一个 .unique() 方法,使我能够在没有重复的情况下进行迭代。 use std::collections::HashSet; struct UniqueState {
我是一名优秀的程序员,十分优秀!