问题描述:

>>> di

{'b': 'B', 'a': 'C'}

>>> print("%s--" % k for k in di.keys())

<generator object <genexpr> at 0x0000000002945360>

原因:语句 "%s--" % k for k in di.keys() 生成了一个迭代器( python generator object)对象,类似C++中的指针和iterator对象.

而 [("%s--" % k for k in di.keys())] 则创建了一个list对象,因此

>>>print(["%s--" % k for k in di.keys()])

就可以正常.

下边是转的关于generator和iterator的文章

Iterator是迭代器的意思,它的作用是一次产生一个数据项,直到没有为止。这样在 for 循环中就可以对它进行循环处理了。那么它与一般的序列类型(list, tuple等)有什么区别呢?它一次只返回一个数据项,占用更少的内存。但它需要记住当前的状态,以便返回下一数据项。它是一个有着next()方法的对象。而序列类型则保存了所有的数据项,它们的访问是通过索引进行的。

使用Iterator的好处除了节省内存外,还有一个好处就是可以把非线性化的处理转换成线性化的方式来进行处理。如对一棵树的访问,传统的方法可以使用递归函数来处理,下面是对树的一个中序遍历的示例:

例1:

def deal_tree(node):
    if not node:
        return
    if node.leftnode:
        deal_tree(node.leftnode)
    process(node)
    if node.rightnode:
        deal_tree(node.rightnode)

deal_tree(root)

可以看出,对结点的处理函数与递归函数是混在一起的,不是很清晰。使用Iterator的方式改写后为:

例2:

1    def walk_tree(node):
2        if not node:
3            return
4        if node.leftnode:
5            for i in walk_tree(node.leftnode):
6                yield i
7        yield node
8        if node.rightnode:
9            for i in walk_tree(node.rightnode):
10               yield i
11
12   for node in wald_tree(root):
13       process(node)

生成结点的过程仍然是一个递归过程,但对于返回后的结点的处理就变成了线性化的处理,结构上要清晰多了。第5-6,9-10行要特别注意,如果不这样处理直接调用walk_tree的话,其实返回的是一个Iterator对象,而不是想要的元素。

象上面的walk_tree函数在 Python 中可以叫作Generator–产生器,它的作用是生成一个Iterator的对象。那么它主要是将一个函数过程进行封装,转化为Iterator对象,每执行到yield语句时,函数的状态,数据都保存起来,然后返回相应的值。取下一个值的时候,再从上次运行的地方继续运行,如果遇上yield语句,则再次保存状态,返回结果,如果不存在值了,则自动引发一个异常StopIteration,从而Iterator不再产生新的值。从此处我们可以了解,这里的Iterator只可以遍历一次,但并非所有的都是这样,你完全可以对其进行控制。

下面我再介绍一下如何构造自已的Iterator。很简单,创建一个类,满足Iterator的协议,也就是要定义__iter__方法,它返回一个Iterator对象,这个对象必须有next方法,因此我们可以总结出两种对象模式:

class A:
    def __iter__(self):
        return self

def next(self):
        if has_next_value(self):
            return next_value
        else:
            raise StopIteration

class B:
    def __iter__(self):
        return iterator_obj

A,B分别为两种对象模式(都是示例代码)。模式A表示,在A中定义了next方法,因此__iter__简单地返回自身即可。当不存在下一个值时,引发StopIteration异常。模式B表示,它使用了其它的Iterator对象,因此只需要定义__iter__即可,next不需要定义,因为返回的Iterator对象已经含有next方法了。如果是自已实现next方法,那么在返回值之前需要记住当前的状态,以便下一次运行时,可以取下一个值。

第2个例子好象与这里讲的不一样啊。这就是前面讲的Generator,它的作用就是把一个函数转换成一个Iterator,它自动保存状态,中间数据,引发异常,全部是自动化了。而且它只可以遍历一次。如果想再次遍历,只有重新生成新的Iterator对象才可以。

在最新的 Python 2.4 版中新增了Genetaor Expression方式,它是用来生成简单的,在函数调用需要序列参数时的一种Iterator写法,语法就象是list comprehension的格式,如:

>>> sum(i*i for i in range(10))                 # sum of squares
285

不过这种写法必须要在小括号对中,因此它的使用是有限的。它的目的主要是想更好的使用内存。

前面我们提到不是所有的Iterator只可以遍历一次(使用Generator生成的只能遍历一次),你完全可以控制它重新遍历。比如我们可以在Iterator对象中增加一个复位方法,用来将内部的计数恢复到开始状态,这样我们就可以重新遍历了。

下面我们总结一下:

Iterator对象:具有__iter__方法,和next方法。当没有新值时引发StopIteration异常。

Iterator的好处:在某些情况下可以使程序结构清晰,如将递归等非线性处理转为线性处理。可以减少内存的占用。

Generator:将一个函数转化成Iterator对象的方法。使用它只需要在函数中需要返回值的时候调用yield语句。它是生成Iterator对象的简单方法,只适用于函数。

generator object genexpr at 0x0000000002731828相关推荐

  1. 报错:<generator object <genexpr> at 0x7fa9adc46eb0>

    python编写队列出现这一报错:<generator object at 0x7fa9adc46eb0>: 例子(简单的起名字系统): x = ['赵','钱','孙','李'] m = ...

  2. Python错误:AttributeError: 'generator' object has no attribute 'next'解决办法

    今天在学习生成器对象(generation object)运行以下代码时,遇到了一个错误: #定义生成器函数 def liebiao(): for x in range(10): yield x #函 ...

  3. 怎样从tensorflow的generator object Estimator.predict at 0x7fb1ecefeaf0中取数据

    怎样从tensorflow的<generator object Estimator.predict at 0x7fb1ecefeaf0>中取数据 通过以下代码: predictions = ...

  4. Hyperopt TypeError: 'generator' object is not subscriptable

    BUG 最近复用以前的代码,结果发现了一个bug,bug如下: File "/home/michael/work/oanda/src/oanda/trend_prediction/find_ ...

  5. scrapy_AttributeError: 'generator' object has no attribute 'meta'''_'generator' 'dont_filter'

    问题描述:初次使用craapy中间件的时候,重写了process_exception方法,目的是反复去调用,但是报错了,如下: 2018-12-26 20:50:57 [scrapy.utils.si ...

  6. NLP的bigrams函数“generator object bigrams at 0x000001D32A95A678“问题解决

    直接输出会产生错误 原因是bigrams函数返回了一个" generator"对象. 这是一种Python数据类型,类似于List,但仅在需要时创建其元素. 如果要将生成器生成列表 ...

  7. python之路day14--列表生成式、生成器generator、生成器并行

    列表生成式 列表生成式阅读量: 44 现在有个需求,现有列表a=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求你把列表里的每个值加1,你怎么实现?你可能会想到2种方式 二逼青年版 ...

  8. 深入理解Python生成器(Generator)

    我们可以通过列表生成式简单直接地创建一个列表,但是受到内存限制,列表容量肯定是有限的.而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,而且如果我们仅仅需要访问前面几个元素,那后面绝大多 ...

  9. python生成器generator:深度学习读取batch图片

    在深度学习中训练模型的过程中读取图片数据,如果将图片数据全部读入内存是不现实的,所以有必要使用生成器来读取数据. 通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而 ...

最新文章

  1. 03 Django REST Framework 视图和路由
  2. Windows10+Virtual box+ubuntu17.10
  3. Spring boot的@PropertySource注解
  4. 做事情不要着急,着急只能把事情做的更加糟糕。。。
  5. 2. TypeScript笔记
  6. mongodb地理空间索引原理阅读摘要
  7. NB-IoT(7)---开发环境搭建及模组驱动开发
  8. 呐,一个苹果洞赚10万美元的详细经验都在这里了~
  9. 用viewpager实现图片轮播
  10. 计算机及移动设备管理软件,终端管理软件
  11. 树莓派(Raspberry Pi)安装五笔输入法,五笔拼音混合输入法
  12. 如何查看IP地址是否被占用
  13. 2022年~全网最真实的软件测试面试题合集
  14. 泛在传感器网络(Ubiquitous Sensor Network; USN)
  15. 动态规划-规划兼职工作
  16. neo4j图数据库Cypher语句
  17. 如何修改tomcat默认的8080端口号
  18. html项目答辩策划书,答辩会策划书范文.doc
  19. 卸载idea步骤(快速彻底)
  20. Qt事例: QScrollArea滚动区域

热门文章

  1. 黑马程序员Maven
  2. Lesson 16 A polite request 彬彬有礼的要求
  3. 如何比较视频编码器的性能
  4. 坐标系概念 四元数 欧拉角
  5. DVWA SQL注入攻击
  6. Latex的使用技巧
  7. HTML5 CSS3专题 诱人的实例 CSS3打造百度贴吧的3D翻牌效果 以及图片提交
  8. gdal坐标转换总结(转换)
  9. postgreSQL触发器
  10. URI、URL、URN区别