python 反射/自省 inspect

自省  

  自省。正如你所知道的,Python 中万物皆对象,自省是指代码可以查看内存中以对象形式存在的其它模块和函数,获取它们的信息,并对它们进行操作。用这种方法,你可以定义没有名称的函数,不按函数声明的参数顺序调用函数,甚至引用事先并不知道名称的函数。


 

 反射

  有时候我们会碰到这样的需求,需要执行对象的某个方法,或是需要对对象的某个字段赋值,而方法名或是字段名在编码代码时并不能确定,需要通过参数传递字符串的形式输入。举个具体的例子:当我们需要实现一个通用的DBM框架时,可能需要对数据对象的字段赋值,但我们无法预知用到这个框架的数据对象都有些什么字段,换言之,我们在写框架的时候需要通过某种机制访问未知的属性。

  这个机制被称为反射(反过来让对象告诉我们他是什么),或是自省(让对象自己告诉我们他是什么,好吧我承认括号里是我瞎掰的- -#),用于实现在运行时获取未知对象的信息。反射是个很吓唬人的名词,听起来高深莫测,在一般的编程语言里反射相对其他概念来说稍显复杂,一般来说都是作为高级主题来讲;但在Python中反射非常简单,用起来几乎感觉不到与其他的代码有区别,使用反射获取到的函数和方法可以像平常一样加上括号直接调用,获取到类后可以直接构造实例;不过获取到的字段不能直接赋值,因为拿到的其实是另一个指向同一个地方的引用,赋值只能改变当前的这个引用而已。

#coding: UTF-8
import sys #  模块,sys指向这个模块对象
import inspect
def foo(): pass # 函数,foo指向这个函数对象
 
class Cat(object): # 类,Cat指向这个类对象
    def __init__(self, name='kitty'):
        self.name = name
    def sayHi(self): #  实例方法,sayHi指向这个方法对象,使用类或实例.sayHi访问
        print self.name, 'says Hi!' # 访问名为name的字段,使用实例.name访问
 
cat = Cat() # cat是Cat类的实例对象
 
print Cat.sayHi # 使用类名访问实例方法时,方法是未绑定的(unbound)
print cat.sayHi # 使用实例访问实例方法时,方法是绑定的(bound)



cat = Cat('kitty')
 
print cat.name # 访问实例属性
cat.sayHi() # 调用实例方法
 
print dir(cat) # 获取实例的属性名,以列表形式返回
if hasattr(cat, 'name'): # 检查实例是否有这个属性
    setattr(cat, 'name', 'tiger') # same as: a.name = 'tiger'
print getattr(cat, 'name') # same as: print a.name
 
getattr(cat, 'sayHi')() # same as: cat.sayHi()

  


 

 获取调用者的详细信息

  •  How to use inspect to get the caller's info from callee in Python?

The caller's frame is one frame higher than the current frame.
You can use inspect.getouterframes to get the caller's frame, plus the filename and line number.

 1 #!/usr/bin/env python
 2 # coding: utf-8
 3 
 4 import inspect
 5 
 6 def hello():
 7   frame,filename,line_number,function_name,lines,index=\
 8     inspect.getouterframes(inspect.currentframe())[1]
 9   print(frame,filename,line_number,function_name,lines,index)
10 hello()
11 
12 # (<frame object at 0x8ba7254>, '/home/unutbu/pybin/test.py', 10, '<module>', ['hello()\n'], 0)

 

 

 

  • How can I get the caller's caller? 

@prosseek: To get the caller's caller, just change the index [1] to [2]. (inspect.getouterframes returns a list of frames...). Python is beautifully organized.

 

 


 

frame records,” each record is a tuple of six items:

the frame object,
the filename,
the line number of the current line,
the function name,
a list of lines of context from the source code,
and the index of the current line within that list.

 


 

 

 

 

 

posted @ 2013-05-03 11:44  tangr206  阅读(680)  评论(0编辑  收藏  举报