python 学习生成器和迭代器 8皇后问题

本文深入探讨了Python中的迭代器和生成器概念,通过实例解释了如何创建和使用这两种对象,并对比了它们与列表的不同之处。此外,还提供了一个使用生成器解决8皇后问题的例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

过去一年的经历和问题

时隔一年后我又回到了我的老地方csdn上面来写我自己的学习经历和一些学到的知识,在这一年中我变换了很多学习的东西但是都没有坚持下来这是我十分遗憾的事情,这一年中我很迷茫,不知道自己的目标是什么,不知道自己想要的是什么。

开头总结一下自己这一年中的一些东西和问题

经历
* 从c#中的asp.net 网站开发学了半年中间也小有成就,开发了我们学院的官方网站和idc机房管理系统,但是都不涉及到高并发、数据安全等一些列的知识,所以总体来说只是一个代码搬运工,对一些orm、mvc等等知识也没有涉及到。算初步入门
* 后面研究了一段时间的unity期间也在csdn中更新了一些自己的学习经历,但是后面也没有坚持下来,最后不了了之,从博客更新的状态上也能大致知晓一二
* 在大三暑假期间也就是在今天的8月份到了成都新蛋科技实习,期间学习了一些在学校期间没有接触到的一些知识,包括orm框架的概念、数据安全、数据库优化和网络方面的知识
* 现在在北京逻辑思维实习,主要方向为python

问题
* 从上述的一些经历中就能大致看出来我最大的问题就是一件事情往往不能持久的进行,不能由浅入深获得足够的竞争里
* 第二个问题就是我的知识面太狭隘,往往不能完整的胜任一份工作,只能简单的进行代码的重复劳动


言归正传

迭代器

可迭代对象 iterable

所有可以被for循环利用的对象称为可迭代对象

>>> L = [1,2,3]
>>> for item in L:
...  print item
...
1
2
3
>>>
>>>

我们可以看到我们的L列表能够被for循环利用所以 L列表称为可迭代对象

迭代器

所有的可迭代对象都可通过内置函数iter()转化为迭代器,和可迭代对象区别就是next()函数

>>> L = [1,2,3]
>>> I = iter(L)
>>> L.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute 'next'
>>> I.next()
1
>>>

iterable继承自object 而iterator继承自iterable
而通常包含了iter()和next()函数的类我们都可以称其为迭代器
下面我们自定义一个迭代器

>>> class ooditer:
...     def __init__(self):
...             self.start = -1
...     def __iter__(self):
...             return self
...     def __next__(self):
...             self.start += 2
...             if self.start > 10:
...                     raise StopIteration
...             return self.start
...
>>> I = ooditer()
>>> for item in I:
...  print(item)
...
1
3
5
7
9
>>> next(I)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 9, in __next__
StopIteration
>>> L = ooditer()
>>> next(L)
1

我们可以看到我们在最上面定义了一个迭代器(返回10以内的奇数)然后利用for循环迭代对象,就输出了10 以内的奇数,然后我们调用next函数我们发现报错了,产生了StopIteration 这里说明我们的迭代器是只向前的,不能向后访问
重新生成一个ooditer的对象然后调用next对象就可以了

注意:只能在python3中使用

生成器

生成器可以理解为一个迭代器,因为生成器可以在我们的for循环中被利用并且在具有next函数

>>> gena = (a for a in range(10))#生成生成器
>>> next(gena)
0
>>>

当然我们可以自定义生成器像这样

>>> def g4():
...  yield 1
...  yield 2
...  yield 3
>>> g = g4()
>>> next(g)
1
>>> next(g)
2
>>> next(g)
3

或者像这样

>>> def odd():
...     n=1
...     while True:
...         yield n
...         n+=2
...
>>> oddnum = odd()
>>> for oddi in oddnum:
...  if oddi > 10:
...   break # 如果我们没有这一行会发生什么
...  print(oddi)
...
1
3
5
7
9

我尝试过通过列表推导式和生成器同时生成一个(1到1000000)的列表
看看它们的执行时间

>>> import datetime
>>> def alisttime():
...  start = datetime.datetime.now()
...  alist = [a for a in range(1000000)]
...  end = datetime.datetime.now()
...  return end-start
...
>>> def blisttime():
...  start = datetime.datetime.now()
...  blist = ( b for b in range(1000000))
...  end = datetime.datetime.now()
...  return end-start
>>> print (alisttime())
0:00:00.050620
>>> print (blisttime())
0:00:00.000024
>>>

我们可以看到同样生成一个1到1000000的数,用生成器明显比列表推导式要快
还有一个很重要的用法就是我们的生成器可以将当前的状态挂起(目前还没有这方面的实际使用方法)

8皇后问题

问题描述
在棋盘中我们有8个皇后,我们要在棋盘中摆放皇后的位置让她们互相不冲突

  • 首先我们定义一个冲突函数
def conflict(state,nextX):
 nextY = len(state)
 for i in range(nextY):
  if abs(state[i]-nextX) in (0,nextY-i):
   return True
 return False

该函数定义的是我们的皇后不在同一垂直线上并且不在对角线上

  • 然后我们定义摆放皇后的函数
def queens(num=8,state=()):
 for pos in range(num):
  if not conflict(state,pos):
   if len(state) == num-1:
    yield (pos,)
   else :
    for result in queens(num, state + (pos,)):
     yield (pos,) + result

如果我们的num不为7那我们就递归执行摆放皇后的函数

  • 最后我们定义一个函数输出我们的棋盘
def prettyprint(solution):
 def line(pos,length=len(solution)):
  return '.' * (pos) + 'X' +'.' * (length-pos-1)
 for pos in solution:
  print line(pos)

下面来看我们的输出
这是其中一个输出值

.......X
...X....
X.......
......X.
.X......
.....X..
..X.....```
我们来看我们一小部分我们的原始输出
(5,)
(3, 5)
(6, 3, 5)
(0, 6, 3, 5)
(2, 0, 6, 3, 5)
(4, 2, 0, 6, 3, 5)
(1, 4, 2, 0, 6, 3, 5)
(7, 1, 4, 2, 0, 6, 3, 5)
(3,)
(6, 3)
(4, 6, 3)
(1, 4, 6, 3)
(5, 1, 4, 6, 3)
(0, 5, 1, 4, 6, 3)
(2, 0, 5, 1, 4, 6, 3)
(7, 2, 0, 5, 1, 4, 6, 3)
(4,)
(6, 4)
(1, 6, 4)
(5, 1, 6, 4)
(2, 5, 1, 6, 4)
(0, 2, 5, 1, 6, 4)
(3, 0, 2, 5, 1, 6, 4)
(7, 3, 0, 2, 5, 1, 6, 4)

我们可以看出来我们的代码并不是顺序执行的,这就是生成器的好处,他将程序挂起等待下一步的执行,从而不影响其他代码的执行

以上纯属个人看法 有考虑不周的地方请指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值