暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Python 基础知识整理 - 类(6)

数据库杂货铺 2021-12-30
283

迭代器

 

到目前为止,我们可能已经注意到,大多数容器对象都可以使用 for 语句进行遍历:

 

for element in [1, 2, 3]:
print(element)


for element in (1, 2, 3):
print(element)


for key in {'one':1, 'two':2}:
print(key)


for char in "123":
print(char)


for line in open("demo.txt", encoding='utf-8'):
print(line, end='')
复制

 

运行结果:

 

1
2
3
1
2
3
one
two
1
2
3
本文件只有这2行内容,1!
本文件只有这2行内容,2!
复制

 

这种访问方式清晰、简洁、方便。迭代器的使用渗透了整个 Python。在后台,for 语句对容器对象调用 iter()。该函数返回一个迭代器对象,该对象定义了 __next__() 方法,该方法每次访问容器中的一个元素。当不再有元素时,__next__() 将引发一个 StopIteration 异常,该异常告诉 for 循环终止。可以使用 next() 内置函数调用 __next__() 方法,下例显示了它的工作原理:

 

s = 'abc'
it = iter(s)
print(it)
print(next(it))
print(next(it))
print(next(it))
print(next(it))
复制

 

运行结果:

 

<str_iterator object at 0x000001E0C8C6F6D0>
a
b
c
Traceback (most recent call last):
File "******", line 7, in <module>
print(next(it))
StopIteration
复制

 

在了解了迭代器协议背后的机制后,将迭代器行为添加到类中是很容易的。定义一个 __iter__() 方法,它返回一个带有 __next__() 方法的对象。如果类定义了 __next__(),则 __iter__() 可以直接返回 self:

 

class Reverse:
def __init__(self, data):
self.data = data
self.index = len(data)


def __iter__(self):
return self


def __next__(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]

rev = Reverse('一二三四五')
print(iter(rev))
for char in rev:
print(char)
复制

 

运行结果:

 

<__main__.Reverse object at 0x000001C01642F160>





复制

 

生成器

 

生成器是创建迭代器的简单而强大的工具。它们像普通函数一样编写,但在需要返回数据时使用 yield 语句。每次调用 next() 时,生成器都会从停止的地方恢复(它记住所有的数据值以及最后执行的语句)。下面的例子说明了生成器很容易创建:

 

def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]


for char in reverse('再向虎山行'):
print(char)
复制

 

运行结果:

 






复制

 

如前所述,任何可以用生成器完成的事情也可以用基于类的迭代器完成。生成器之所以如此紧凑,是因为 __iter__() __next__() 方法是自动创建的。

 

另一个关键特性是在调用之间自动保存本地变量和执行状态。这使得函数更容易编写,也比使用 self.index self.data 这样的实例变量的方法更清晰。

 

除了自动创建方法和保存程序状态外,当生成器终止时,还会自动引发 StopIteration。结合起来,这些特性使得创建迭代器非常容易。

 

生成器表达式

 

一些简单的生成器可以被简洁地编码为表达式,使用类似于列表推导式的语法,但使用圆括号而不是方括号。这些表达式是为生成器被一个封闭函数直接使用的情况设计的。生成器表达式比完整的生成器定义更紧凑,但不够通用,并且比等价的列表推导式更容易记忆。

 

例子:

 

sumresult = sum(i*i for i in range(10))
print(sumresult)


xvec = [10, 20, 30]
yvec = [7, 5, 3]
sumproduct = sum(x*y for x,y in zip(xvec, yvec))
print(sumproduct)


data = '再向虎山行'
listresult = list(data[i] for i in range(len(data)-1, -1, -1))
print(listresult)
复制

 

运行结果:

 

285
260
['行', '山', '虎', '向', '再']
复制

 

 

 

官方文档:

https://docs.python.org/3.9/tutorial/classes.html


文章转载自数据库杂货铺,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论