我的Python3.0笔记之容器,迭代器,生成器

来源:互联网 发布:js获取input text的值 编辑:程序博客网 时间:2024/06/14 17:59

      在面向对象的语言中,大都有容器这一数据结构,容器其实是一组相同类型对象的集合,基本上可以容纳所有类型的数据。

  C++中的容器类包括“顺序存储结构”和“关联存储结构”,前者包括vector,list,deque等;后者包括set,map等。Python中容器主要是:列表,元组,字符串,字典(映射),集合,自定义类型。


 一、 Python中的迭代器(iterator),一般迭代器对象都有__init__方法和__next__方法。可以这么说:一个实现了__init__方法的对象是可迭代的,一个实现了__next__方法的对象则是迭代器。__init__方法返回迭代器自身,__next__方法返回它的下一个值,如果没有值可以返回了,就会抛出一个StopIteration异常。


python迭代器的优势:

  1、用for循环加列表,读取列表时会一次性加载所有值,占用内存过多;迭代器则是有需要时才生成一个值返回;

  2、对于没有索引的数据类型,必须提供一种不依赖索引的迭代方式。

缺点:
  1. 无法获取迭代器对象的长度;
  2. 不如序列类型取值灵活,是一次性的,只能往后取值,不能往前退。


每次调用__next__()方法的时候做两件事: 

  1. 为下一次调用__next__()方法修改状态
  2. 为当前这次调用生成返回结果

每次调用__iter__()时返回它本身。


# 用Fibonacci数列举例:

###########

class Fibonacci:

  def __init__(self):

    self.a = 0

    self.b = 1

 def __next__(self):

    #为下一次调用__next__()方法修改状态

    self.a, self.b = self.b, self.a+self.b

    #为当前这次调用生成返回结果

    return self.a

  def __iter__(self):

    return self

#生成一个斐波那契对象

fibs = Fibonacci()

#每次调用__next__方法返回下一个值,打印前10个斐波那契数

for i in range(10):

  print(fibs.__next__())

#找到第一个大于1000的斐波那契数后打印并跳出循环

for f in fibs:

  if f > 1000:

    print(f)

    break

###########

  安全问题运行结果不能上传,以后补充。

  Python3以后,range()和xrange()都成为了range(),也就是说现在range()返回的也是一个特殊迭代器。如果想返回列表,给它套一个list()。

 


  二、Python中的生成器(generator)是一个特殊的迭代器(延迟操作),首先任何包含yield语句的函数称为生成器。它不用return返回值,而是每次产生多个值。每次产生一个值(使用yield语句),函数就会被冻结:函数停在那点等待被重新唤醒。被重新唤醒后就从停止的那点开始执行。因此特别适合不想同一时间将所有计算出来的大量结果集分配到内存当中时的场景,特别是当结果集里还包含循环的时候。

  也就是说,yield是一个语法糖,内部实现支持了迭代器协议,同时yield内部是一个状态机,维护着挂起和继续的状态。

  yield的功能:
  1.相当于为函数封装好__iter__和__next__
  2.return只能返回一次值,函数就终止了,而yield能返回多次值,每次返回都会将函数暂停,下一次next会从上一次暂停的位置继续执行。


###########

# 生成器函数

def fibonacci(n):

  a = 0

  b = 1

  for i in rang(n):

    a, b = b, a+b

    yeild a

# 对内存非常友好,百万位也没问题

for i in fibonacci(1000000):

  print(i)


###########


 生成器推导式,和列表推导式的工作方式类似,不过将[]变成(),且返回的不是列表而是生产器,要想得到每一个元素,可以用循环或者next()。


###########

li = [1,2,3,4,5,6,7]

#生成器推导式,类似list,把[]改为()

gen = (a for a in li)

for x in gen:

  print(x)

# 使用生成器表达式取代列表推导式可以同时节省cpu和内存RAM

# 如果你构造一个列表的目的仅仅是传递给别的函数,如tuple()或set(),就用生成式表达式代替吧


#例如直接把列表转化为元组

q = tuple(a for a in li)

print(q)


#Python内置的一些函数可以识别这是生成器表达式,生成器表达式可以在当前圆括号内直接使用

result1 = sum(a for a in range(3))

print(result1)

#列表推导式

result2 = sum([a for a in range(3)])

print(result2)

############

之后补充n皇后的例子,因为Python语句的强大,比C++可以写得更简洁。



原创粉丝点击