python - 如何检查 Generator 类型对象?

标签 python python-2.7 generator coroutine yield-keyword

使用以下代码(第一种情况),

def f():
   mylist = range(3)
   for i in mylist:
      yield i*i

如果不检查y,您是否可以说,y=f() 返回(x*x for x in range(3)) collections.abc.Generator 类型的对象?

<小时/>

使用下面的代码(第二种情况),

def func():
    x = 1
    while 1:
        y = yield x
        x += y

调用y=func()时返回的Generator类型对象是什么?如何检查y以查看代码?

最佳答案

第一种情况——简单生成器

generator expression (x*x for x in range(3))simple generator 大致相同你描述的功能。然而,genexp 的作用域可能会稍微复杂一些(这就是为什么我们通常建议您立即使用生成器表达式而不是传递它们)。

第二种情况——增强型生成器

带有 y = yield x 的代码是 enhanced generator 的示例。它用于将数据发送到正在运行的生成器中,本质上是在正在运行的生成器和调用代码之间创建双向通信 channel 。

发送/接收逻辑的主要用例是实现协程和生成器蹦床。看这个trampoline example来自大卫·比兹利。

增强的生成器是 Twisted Python 美丽的关键 Inline Callbacks其中实现 coroutines .

如何检查生成器

对于y = func()中的变量y,唯一的检查技术是检查公共(public)API:

>>> y = func()
>>> dir(y)
['__class__', '__delattr__', '__doc__', '__format__',
 '__getattribute__', '__hash__', '__init__', '__iter__',
 '__name__', '__new__', '__reduce__', '__reduce_ex__',
 '__repr__', '__setattr__', '__sizeof__', '__str__',
 '__subclasshook__', 'close', 'gi_code', 'gi_frame',
 'gi_running', 'next', 'send', 'throw']

如何检查生成器函数

对于生成器函数本身,您可以使用dis模块来检查代码以了解其工作原理:

>>> def func():
        x = 1
        while 1:
            y = yield x
            x += y

>>> import dis
>>> dis.dis(func)
  3           0 LOAD_CONST               1 (1)
              3 STORE_FAST               0 (x)

  4           6 SETUP_LOOP              21 (to 30)

  5     >>    9 LOAD_FAST                0 (x)
             12 YIELD_VALUE         
             13 STORE_FAST               1 (y)

  6          16 LOAD_FAST                0 (x)
             19 LOAD_FAST                1 (y)
             22 INPLACE_ADD         
             23 STORE_FAST               0 (x)
             26 JUMP_ABSOLUTE            9
             29 POP_BLOCK           
        >>   30 LOAD_CONST               0 (None)
             33 RETURN_VALUE 

使用调试器跟踪代码

您可以使用pdb调试器逐步跟踪代码。

>>> import pdb
>>> y = func()
>>> pdb.runcall(next, y)
> /Users/raymond/Documents/tmp.py(2)func()
-> x = 1
(Pdb) s
> /Users/raymond/Documents/tmp.py(3)func()
-> while 1:
(Pdb) s
> /Users/raymond/Documents/tmp.py(4)func()
-> y = yield x
(Pdb) p locals()
{'x': 1}
(Pdb) s
> /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/bdb.py(440)runcall()
-> self.quitting = 1
(Pdb) s
1
>>> pdb.runcall(y.send, 10)
> /Users/raymond/Documents/tmp.py(5)func()->1
-> x += y
(Pdb) s
> /Users/raymond/Documents/tmp.py(4)func()->1
-> y = yield x
(Pdb) locals()
{'__return__': 1, 'x': 11, 'y': 10}

关于python - 如何检查 Generator 类型对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44581427/

相关文章:

gwt - 如何为 GWT RPC 集中 "loading"屏幕?

python - 在Python中,根据转移概率为TSP生成随机路径

python - 将 INSERT 切换为 REPLACE 会使 DATE_SUB() 结果无效

python - 返回列表的第一个数字

Python 和矩阵

python-2.7 - Pycharm 调试器错误

php - 生成器不能处于闭包状态

python - 当网络套接字始终准备好读取时如何使用 select?

python - 异常处理 block 的正确范围

Python排序两个键两个顺序