今天接觸了下pyUSB,事先沒看對象內部成員資料,直接用python的dir函數看了看pyUSB的內部構成。忽然間想到本身可不能夠寫個簡單的腳本,利用dir或其餘函數遍歷某個對象內部的全部成員,並打印出來成樹狀圖的形式?因而寫了以下對象分析程序:python
使用方法 :app
import matplotlib.pyplot as plt import AnalysisClass m = AnalysisClass.AnalysisClass() m.analysisObject(plt.Arrow, 'plt.Arrow', 'plt.txt', levelEnd=3)
調用analysisObject便可分析matplotlib的pyplot庫內部的成員,並把全部成員函數、成員類以及各成員的__doc__前兩行做爲概述打印出來。上面的plt.Arrow是要分析的對象,’plt.Arrow’是要分析對象的名稱字符串,’plt.txt’是用來保存分析結果的文件名,levelEnd用來指定遞歸的深度。函數
上面調用獲得的結果:ui
省略若干行this
代碼概述:spa
程序核心很簡單,就是遞歸地用dir()函數獲得對象的全部成員,對於如下劃線開頭的內部成員不予處理,其餘的如常量(通常全大寫)、成員函數、成員類等的名字則保存起來,而後在以這些成員爲對象遞歸地獲取下一層的成員列表。code
詳細程序:對象
import types class AnalysisClass: def __init__(self): self.level= 0 self.file = None self.constNum=[] self.funcNum = [] def _levelTreePrint(self, strs, isConst=False): levelTab=self.level*4*' ' levelStrHead =[i for i in levelTab] if self.level != 0: # strs = str(self.funcNum[-1])+strs for i in range(self.level): if (not isConst) and self.funcNum[i] == 1: continue else: levelStrHead[i*4+1] = '|' levelStrHead[((self.level-1)*4+2):] = ['-','-'] levelStrHead = ''.join(levelStrHead) levelStr = levelStrHead+strs else: levelStr = strs print levelStr if self.file != None: self.file.writelines(levelStr+'\n') # def _isListOrTuple(self, cla): # if type(cla)==types.ListType or type(cla)==types.TupleType: # return True # else: # return False def _hasAvailableCla(self, cla): mems = dir(cla) constMem=[] claOrFuncMem = [] constMaxLen = 0 funcMaxLen = 0 for i in mems: lenI = len(i) if i[0] == '_': # No inner function or inner constants continue if i.isupper(): if lenI>constMaxLen: constMaxLen = lenI constMem.append(i) elif i[0:2]!='__' and i[-2:]!='__':# No buildin functions if lenI>funcMaxLen: funcMaxLen = lenI claOrFuncMem.append(i) return (constMem, constMaxLen, claOrFuncMem, funcMaxLen) def _printConstMem(self, cla, constMem, constMaxLen): loc_var = locals() for i in loc_var.iteritems(): if id(i[1]) == id(cla): cla_loc_name = i[0] for i in constMem: tmp = eval(cla_loc_name+'.'+i) i = i.ljust(constMaxLen+1, ' ') # if type(tmp)==types.IntType: # i = i+"(%d)"%tmp # else: # i = i+"(NOT AN INT NUMBER)"+str(type(tmp)) i = i + "(%s)"%str(tmp) self._levelTreePrint(i, isConst=True) self.constNum[-1] -= 1 def _printClaOrFuncMem(self,cla, cla_name, funcMaxLen, claOrFuncMem): loc_var = locals() for i in loc_var.iteritems(): if id(i[1]) == id(cla): cla_loc_name = i[0] for i in claOrFuncMem: iMem = cla_loc_name+'.'+i iMemReName = cla_name+'.'+i try: if None!=eval(iMem): self._analysisClass(eval(iMem),iMemReName, maxClaNameLen = funcMaxLen) self.level -= 1 else: self._levelTreePrint(cla_name.split('.')[-1]+'.'+i+"--'Nothing'") except Exception,e: pass self.funcNum[-1] -= 1 def _analysisClass(self, cla, cla_name, maxClaNameLen = 0): if hasattr(cla, "__doc__"): doc = str(cla.__doc__).split('\n') if len(doc)>=2: doc = doc[0]+doc[1] else: doc = doc[0] else: doc = ' ' if self.level!=0 and maxClaNameLen!=0: sNameTmp = cla_name.split('.') extraLen = len(sNameTmp[-2]) sName = sNameTmp[-2]+'.'+sNameTmp[-1] cla_name_tmp = sName.ljust(extraLen+maxClaNameLen+1,' ') else: cla_name_tmp = cla_name self._levelTreePrint(cla_name_tmp+':'+str(type(cla))+3*'-'+"\""+doc+"\"") self.level += 1 if self.level == self.levelEnd: return (constMem, constMaxLen, claOrFuncMem, funcMaxLen) = self._hasAvailableCla(cla) if constMaxLen != 0: self.constNum.append(len(constMem)) self._printConstMem(cla, constMem, constMaxLen) self.constNum.pop() if funcMaxLen != 0: self.funcNum.append(len(claOrFuncMem)) self._printClaOrFuncMem(cla, cla_name, funcMaxLen, claOrFuncMem) self.funcNum.pop() else: return #=========================================================================== # Analysis the stucture of 'obj'.This function will list out the members of the object as # a tree. # @param obj - object,can be class,module,package,etc # @param obj_name - object name string,should be same to the actual name of 'obj' # @param file_name - If you want to store the analysis info to a txt file,set this param # of your file name # @paramm levelEnd - set the recursion limits.The analysisObject function will recursively # enum all the members of the 'obj',when the recursion depth equals levelEnd # the function will stop automatically # # Using: # import AnalysisClass # import matplotlib.pyplot as plt # m = AnalysisClass.AnalysisClass() # m.analysisObject(plt.Annotation, 'plt.Annotation', 'plt.txt', levelEnd=4) # Written by Liu.2014-07-25 #=========================================================================== def analysisObject(self, obj, obj_name, file_name=None, levelEnd=3): if file_name != None: self.file = open(file_name, 'w') self.levelEnd = levelEnd self._analysisClass(obj, obj_name, levelEnd) if self.file !=None: self.file.close()