标签:dict 执行 assm comm __name__ 遍历 func 语句 元素
迭代: 访问集合元素的一种方式. 通常把使用for循环取数的过程称为遍历, 也叫迭代.
可迭代对象(Iterable): 把可以通过for…in…这类语句迭代读取?条数据供我们使?的对象称之为可迭代对象.
很多容器都是可迭代对象(iterable), 并不是所有容器都是可以迭代的;但凡可以返回一个迭代器的对象都是可迭代对象;
容器: 这个称呼在其他博客上看到的, 了解下; 一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用in
, not in
关键字判断元素是否包含在容器中 . 常见的str, list, set, dict都是容器
可以使用 isinstance() 判断一个对象是否是 Iterable 对象
1 2 3 4 5 6 7 8
| from collections import Iterable
print(isinstance([], Iterable)) print(isinstance((), Iterable)) print(isinstance({}, Iterable)) print(isinstance("", Iterable)) print(isinstance(100, Iterable)) print(isinstance(False, Iterable))
|
1.迭代器iterator
迭代器: 任何实现了__iter__
和__next__()
(python2中实现next()
)方法的对象都是迭代器;
__iter__
返回迭代器自身,__next__
返回容器中的下一个值,如果容器中没有更多元素了,则抛出StopIteration异常
在遍历过程中就应该有一个“人”去记录每次访问到了第几条数据,以便每次迭代都可以返回下一条数据。我们把这个能帮助我们进行数据迭代的“人”称为迭代器(Iterator)。可迭代对象的本质就是提供一个这样的中间“人”即迭代器帮助我们对其进行迭代遍历使用。
- 可迭代对象的本质就是提供一个这样的中间“人”即迭代器帮助我们对其进行迭代遍历使用
- 可迭代对象是一个具备了
__iter__
方法的对象,通过__iter__
方法获取可迭代对象的迭代器
迭代器本质上是一个产生值的工厂,每次向迭代器请求下一个值,迭代器都会进行计算出相应的值并返回。
可以通过iter()函数获取这些可迭代对象的迭代器, 然后可以对获取到的迭代器不断使用next()函数来获取下一条数据。
1 2 3 4 5 6 7 8
| li = [11, 22, 33, 44, 55]
iterator = iter(li)
print(next(iterator)) print(next(iterator))
|
1.1 __iter__
和__next__
迭代器首先是一个可迭代对象, 可迭代对象必须实现__iter__
方法
迭代器同时要能够返回可迭代对象的下一个值,所以当调用next()函数的时候,需要能够返回值,所以必须定义next方法;
1.2 for循环
for item in Iterable 循环的本质就是先通过iter()函数获取可迭代对象Iterable的迭代器,然后对获取到的迭代器不断调用next()方法来获取下一个值并将其赋值给item,当遇到StopIteration的异常后循环结束。
1.3 代码实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| import collections
class (object): def __init__(self): self.names = [] self.current = 0
def add(self, name): self.names.append(name)
def __iter__(self): """通过该方法取得迭代器对象""" return self
def __next__(self): """取得下一个迭代的值""" if self.current < len(self.names): name = self.names[self.current] self.current += 1 return name else: raise StopIteration
my_classmate = MyClassmate() my_classmate.add("小王") my_classmate.add("小李") my_classmate.add("小张")
print(isinstance(my_classmate, collections.Iterable))
for name in my_classmate: print(name)
|
1.4 应用场景
斐波拉契序列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class FibIterator(object): """斐波那契数列迭代器"""
def __init__(self, n): """初始化属性""" self.n = n self.current_index = 0 self.num1 = 0 self.num2 = 1
大专栏 迭代器和生成器ion">def __next__(self): """被next()函数调用来获取下一个数""" if self.current_index < self.n: num = self.num1 self.num1, self.num2 = self.num2, self.num1 + self.num2 self.current_index += 1 return num else: raise StopIteration
def __iter__(self): """迭代器的__iter__返回自身即可""" return self
if __name__ == '__main__': fib = FibIterator(10) for num in fib: print(" ", num, end="")
|
运行结果: 0 1 1 2 3 5 8 13 21 34
2.生成器generator
生成器: 可以理解为一个特殊的迭代器。调用这个函数就得到一个迭代器,生成器中的yield相当于一个断点,执行到此返回一个值后暂停,从而实现next取值。
- 任意生成器都是迭代器(反过来不成立)
- 任意生成器,都是一个可以延迟创建值的工厂
它不需要再像上面的类一样写__iter__()
和__next__()
方法了,只需要一个yiled
关键字。
2.1 创建生成器方法
2.1.1 把列表生成式的[] 改成()
1 2 3 4 5 6 7 8
| L=[x*2 for x in range(6)] print(L)
G=(x*2 for x in range(6))
print(G)
|
2.1.2 列表生成式
用生成器实现斐波拉契序列
1 2 3 4 5 6 7 8
| def fib(): """斐波拉契函数""" prev, curr = 0, 1 while True: yield curr prev, curr = curr, curr + prev f = fib() print(list(islice(f,0, 10)))
|
fib
就是一个普通的python函数,它特殊的地方在于函数体中没有return
关键字,函数的返回值是一个生成器对象。当执行f=fib()
返回的是一个生成器对象,此时函数体中的代码并不会执行,只有显示或隐示地调用next的时候才会真正执行里面的代码。
另外一种写法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| def fib(n): curr_index = 0 num1, num2 = 0, 1 while curr_index < n: """ 1. 假如函数中有yield,则不再是函数,而是生成器 2. yield 会产生一个断点 3. 假如yield后面紧接着一个数据,就会把数据返回, 作为next()函数或者for ...in...迭代出的下一个值 """ yield num1 num1, num2 = num2, num1 + num2 curr_index += 1 if __name__ = '__main__': G = fib(5) for num in G print("", num, end="")
|
2.2 生成器总结
- 使用了yield关键字的函数不再是函数,而是生成器。(使用了yield的函数就是生成器)
- yield关键字有两点作用:
- 保存当前运行状态(断点),然后暂停执行,即将生成器(函数)挂起
- 将yield关键字后面表达式的值作为返回值返回,此时可以理解为起到了return的作用
- 可以使用next()函数让生成器从断点处继续执行,即唤醒生成器(函数)
2.3 使用send
我们除了可以使用next()函数来唤醒生成器继续执行外,还可以使用send()函数来唤醒执行。使用send()函数的一个好处是可以在唤醒的同时向断点处传入一个附加数据。
执行到yield时,gen函数会暂停,返回i的值; temp接收下次obj.send(“haha”)发送过来的值,next(obj)等价obj.send(None)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| def gen(): i = 0 while i < 5: temp = yield i print(temp) i += 1
if __name__ == '__main__': obj = gen()
print(next(obj)) print(next(obj))
print(obj.send("haha")) print(next(obj))
print(obj.send("python"))
|
迭代器和生成器
标签:dict 执行 assm comm __name__ 遍历 func 语句 元素
原文地址:https://www.cnblogs.com/lijianming180/p/12255807.html