003_生成器(generator)内部解析

#http://kb.cnblogs.com/page/87128/(未看完)

2.7. 生成器(generator)

  生成器是调用一个生成器函数(generator function)返回的对象,多用于集合对象的迭代。

  • __iter__: 仅仅是一个可迭代的标记。
  • gi_code: 生成器对应的code对象。
  • gi_frame: 生成器对应的frame对象。
  • gi_running: 生成器函数是否在执行。生成器函数在yield以后、执行yield的下一行代码前处于frozen状态,此时这个属性的值为0。
  • next|close|send|throw: 这是几个可调用的方法,并不包含元数据信息,如何使用可以查看生成器的相关文档。
def gen():
for n in xrange(5):
yield n
g = gen()
print g # <generator object gen at 0x...>
print g.gi_code # <code object gen at 0x...>
print g.gi_frame # <frame object at 0x...>
print g.gi_running # 0
print g.next() # 0
print g.next() # 1
for n in g:
print n, # 2 3 4

接下来讨论的是几个不常用到的内置对象类型。这些类型在正常的编码过程中应该很少接触,除非你正在自己实现一个解释器或开发环境之类。所以这里只列出一部分属性,如果需要一份完整的属性表或想进一步了解,可以查看文末列出的参考文档。

2.8. 代码块(code)

  代码块可以由类源代码、函数源代码或是一个简单的语句代码编译得到。这里我们只考虑它指代一个函数时的情况;2.5节中我们曾提到可以使用函数的func_code属性获取到它。code的属性全部是只读的。

  • co_argcount: 普通参数的总数,不包括*参数和**参数。
  • co_names: 所有的参数名(包括*参数和**参数)和局部变量名的元组。
  • co_varnames: 所有的局部变量名的元组。
  • co_filename: 源代码所在的文件名。
  • co_flags:  这是一个数值,每一个二进制位都包含了特定信息。较关注的是0b100(0x4)和0b1000(0x8),如果co_flags & 0b100 != 0,说明使用了*args参数;如果co_flags & 0b1000 != 0,说明使用了**kwargs参数。另外,如果co_flags & 0b100000(0x20) != 0,则说明这是一个生成器函数(generator function)。
co = cat.sayHi.func_code
print co.co_argcount # 1
print co.co_names # ('name',)
print co.co_varnames # ('self',)
print co.co_flags & 0b100 # 0

2.9. 栈帧(frame)

  栈帧表示程序运行时函数调用栈中的某一帧。函数没有属性可以获取它,因为它在函数调用时才会产生,而生成器则是由函数调用返回的,所以有属性指向栈帧。想要获得某个函数相关的栈帧,则必须在调用这个函数且这个函数尚未返回时获取。你可以使用sys模块的_getframe()函数、或inspect模块的currentframe()函数获取当前栈帧。这里列出来的属性全部是只读的。

  • f_back: 调用栈的前一帧。
  • f_code: 栈帧对应的code对象。
  • f_locals: 用在当前栈帧时与内建函数locals()相同,但你可以先获取其他帧然后使用这个属性获取那个帧的locals()。
  • f_globals: 用在当前栈帧时与内建函数globals()相同,但你可以先获取其他帧……。
def add(x, y=1):
f = inspect.currentframe()
print f.f_locals # same as locals()
print f.f_back # <frame object at 0x...>
return x+y
add(2)
posted @ 2016-04-02 04:34  arun_python  阅读(405)  评论(0编辑  收藏  举报