Python中的迭代器,python生成器与迭代器

  Python中的迭代器,python生成器与迭代器

  本文主要介绍python中的迭代器和生成器。本文通过示例代码给你做了非常详细的介绍,对你的学习或者工作有一定的参考价值。有需要的朋友可以参考一下。

  

可迭代对象和迭代器

  迭代意味着重复,就像for循环迭代序列和字典一样,但其实for循环也可以用来迭代其他对象:实现方法_ _ iterator _ _(迭代器协议的基础)的对象。

  __iter__方法返回一个迭代器,迭代器是包含方法__next__的对象,可以不带任何参数调用;

  当你调用__next__,迭代器应该返回它的下一个值;如果没有值要返回,应该抛出StopIteration异常;

  也可以使用内置函数next(),在这种情况下next(it)与它等效。__next()__。

  至于为什么不用列表?因为在很多情况下,使用列表有点浪费。例如,如果你有一个可以逐个计算值的函数,你可能只想逐个获取值,而不是使用一个列表一次性获取所有值。这是因为如果有很多值,列表可能会占用太多内存。

  我们来看一个不能使用链表的例子,因为如果使用了,这个链表的长度将是无限的!

  #这个“列表”就是斐波那契数列,也就是说这个数列的迭代器如下:

  Fibs:级

  def __init__(self):

  self.a=0

  self.b=1

  def __next__(self):

  self.a,self.b=自我

  自我。逻辑前面定义了一个#,最后可以返回下一个值。

  def __iter__(self):

  Return #返回迭代器本身(包含__next__方法的对象)

  fibs=Fibs()

  对于fibs:中的f

  如果f 1000:

  打印(f) # 1597

  Break #如果你不中断循环,它会继续循环。

  下一个(谎言)# 2584

  下一个(谎言)# 4181

  更正式地说,实现方法__iter__的对象是迭代的,实现方法__next__的对象是迭代器。

  

内置函数 iter()

  可以通过调用iterable对象上的内置函数iter()来获得迭代器。您还可以使用它从函数或其他可调用对象中创建可迭代对象。

  但iterable对象转换成迭代器后,会丢失一些属性(如__getitem__()),但同时会增加一些属性(如__next__())。

  另外,迭代器一般是次要的,迭代后,再次迭代后不会得到元素。迭代对象可以重用。

  It=iter([1,2,3]) # list是一个迭代对象。

  下一个(它)# 1

  下一个(它)# 2

  下一个(它)# 3

  下一个(它)# StopIretation的普通可迭代对象是可重用的,而迭代器是一次性的,不能返回。

  It=iter(ABCD) # string也是可迭代对象。

  因为我在it:

  print(i,end= ) # A B C D

  因为我在it:

  Print (i,end=) # output

  有四种方法可以查看对象是否实现了神奇的method _iter_:

  #方法一:DIR () Check __iter__,详情请自行尝试。

  目录(2) #号

  目录( abc) #有__iter__()

  #方法2: isinstance()判断

  导入收藏

  isinstance(2,集合。Iterable) # False

  isinstance(abc ,集合。Iterable) # True

  #方法3: Hasattr()判断

  hasattr(2, __iter__) # False

  hasattr(abc , __iter__) # True

  #方法4: ITER()检查是否报告了错误。

  Iter(2) #报告了一个错误:“int”对象不可迭代

  iter(abc) # str_iterator位于0x1e2396d8f28

  

从迭代器创建序列

  当可以使用序列时,大多数情况下也可以使用迭代器或可迭代对象(索引和切片等操作除外)。因为迭代器缺少__getitem__,无法做出普通的切割语法,所以我们还没有研究过。

  #使用构造函数列表()显示迭代器。

  转换为列表

  class TestIterator:

   value = 0

   def __next__(self):

   self.value += 1

   if self.value > 10: raise StopIteration

   return self.value

   def __iter__(self):

   return self

  ti = TestIterator()

  ti2 = list(ti) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

  for i in ti2:

   print(i, end=" ") # 1 2 3 4 5 6 7 8 9 10

  print(the second:)

  

  

生成器

  生成器,也被称为简单生成器(simple generator),生成器自动创建了 iter() 和 next() 方法,是一种使用普通函数语法定义的迭代器。与函数的主要的形式差别就在于,它的函数体中有一句 yield 语句。
每次执行到 yield 处时,生成并返回一个值后,函数都将暂时停止执行,等待下一轮迭代调用,如此往复,直到迭代完。数据量大时,生成器能够极大地节省内存空间。下面还是通过斐波纳契数列来看看:

  

# 斐波纳契数列的生成器实现: 返回数列的前 n 项

  def fibs(n):

   a, b = 0, 1

   for _ in range(n):

   yield a # 返回的是一个生成器

   a, b = b, b+a

  f = fibs(5)

  print(f) # <generator object fibs at 0x05BB20B0>

  print(list(f)) # [0, 1, 1, 2, 3]; 此处生成器 f 已经被迭代过一次了

  for i in f:

   print(i, end=" ") # ⽆输出; for循环会⾃动捕捉到 StopIteration 异常并停⽌调⽤ next()

  print(next(f)) # StopIteration

  与 return 的区别:生成器不是像 return 一样返回一个值,而是可以生成多个值,每次返回一个;return 返回的话,这个函数就结束了。

  

生成器推导(生成式表达式)

  将列表生成式的 [] 改成 () 之后,数据结构将从列表变为生成器,而不是元组。如果要包装可迭代对象(可能生成大量的值)时,若使用列表推导将立即实例化一个列表,从而丧失迭代的优势;但如果使用生成器推导的话,每迭代一次就生成一个值,没必要一次性生成全部值,这样就好的多了。而且,可以直接在既有的圆括号内(如在函数调用中)使用生成器推导时,无需再添加一对圆括号。

  

L = [x*x for x in range(10)] # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

  g = (x*x for x in range(10)) # <generator object <genexpr> at 0x052AF8F0>

  print(next(g)) # 0

  sum(i ** 2 for i in range(10)) # 285

  

递归式生成器

  创建一个将两层嵌套列表展开的函数:

  

nested = [[1, 2], [3, 4], [5], 6]

  def flatten(nested):

   try:

   for sub in nested:

   for ele in sub:

   yield ele

   except TypeError:

   yield sub

  f = flatten(nested)

  next(f) # 1

  # print(list(f)) # [2, 3, 4, 5, 6]

  for i in f3:

   print(i) # 2 3 4 5 6

  创建一个将任意层嵌套列表展开的函数:
对一层列表进行遍历,遍历下层列表的时候,先对一层遍历出来的元素再调用一次 flatten 函数,这时,如果是不可再迭代的对象的话,就会报 TypeError 错误,捕捉到之后,yeild 返回,继续下一个;如果是可迭代的话,就递归下去;

  

def flatten(nested):

   try:

   for sub in nested:

   for ele in flatten(sub):

   yield ele

   except TypeError:

   yield nested

  nested = [[[1], 2], 3, 4, [5, [6, 7]], 8]

  print(list(flatten(nested)))

  不过,上面要注意的是:前面也提到了,字符串对象也是可迭代的,而且一般我们也不会将它拆开。更重要的是,字符串的第一个元素是一个长度为 1 的字符串,而长度为 1 的字符串的第一个元素是字符串本身。

  

s = ABCD

  s2 = s[0] # A

  s2[0] # A

  这样子会造成无穷递归的。所以还需要检查一下对象是否类似于字符串:

  

def flatten(nested): 

   try:

   if isinstance(nested, str): raise TypeError

   for sub in nested:

   for ele in flatten(sub):

   yield ele

   except TypeError:

   yield nested

  nested = [[[1], 23], 3, 43, [5, [6, 73]], 8]

  print(list(flatten(nested))) # [1, 23, 3, 43, 5, 6, 73, 8]

  不过,它有两个 yield 唉,这认哪个来着???pass

  

def flatten(nested):

   try:

   for sublist in nested:

   for element in flatten(sublist):

   print("element:", element)

   yield element

   except TypeError:

   print("nested :", nested)

   yield nested

  print(list(flatten([[1, 2], [3, 4], [5], 6])))

  输出:

  

nested : 1
element: 1
nested : 2
element: 2
nested : 3
element: 3
nested : 4
element: 4
nested : 5
element: 5
nested : 6
element: 6
[1, 2, 3, 4, 5, 6]

  

  到此这篇关于python 中的迭代器和生成器简单介绍的文章就介绍到这了,更多相关python 迭代器和生成器内容请搜索盛行IT软件开发工作室以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT软件开发工作室!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: