python动态函数名 python动态参数应用( 四 )


下面的代码演示了func_closure:
#coding: UTF-8
def foo():
n = 1
def bar():
print n # 引用非全局的外部变量n,构造一个闭包
n = 2
return bar
closure = foo()
print closure.func_closure
# 使用dir()得知cell对象有一个cell_contents属性可以获得值
print closure.func_closure[0].cell_contents # 2
由这个例子可以看到,遇到未知的对象使用dir()是一个很好的主意 :)
2.6. 方法(method)
方法虽然不是函数,但可以理解为在函数外面加了一层外壳;拿到方法里实际的函数以后,就可以使用2.5节的属性了 。
__doc__: 与函数相同 。
__name__: 与函数相同 。
*__module__: 与函数相同 。
im_func: 使用这个属性可以拿到方法里实际的函数对象的引用 。另外如果是2.6以上的版本 , 还可以使用属性名__func__ 。
im_self: 如果是绑定的(bound),则指向调用该方法的类(如果是类方法)或实例(如果是实例方法),否则为None 。如果是2.6以上的版本 , 还可以使用属性名__self__ 。
im_class: 实际调用该方法的类,或实际调用该方法的实例的类 。注意不是方法的定义所在的类,如果有继承关系的话 。
im = cat.sayHi
print im.im_func
print im.im_self # cat
print im.im_class # Cat
这里讨论的是一般的实例方法 , 另外还有两种特殊的方法分别是类方法(classmethod)和静态方法(staticmethod) 。类方法还是方法,不过因为需要使用类名调用,所以他始终是绑定的;而静态方法可以看成是在类的命名空间里的函数(需要使用类名调用的函数),它只能使用函数的属性 , 不能使用方法的属性 。
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(0×4)和0b1000(0×8) , 如果co_flags0b100 != 0 , 说明使用了*args参数;如果co_flags0b1000 != 0,说明使用了**kwargs参数 。另外,如果co_flags0b100000(0×20) != 0,则说明这是一个生成器函数(generator function) 。

推荐阅读