2010-03-04 11 views
7

Ho un AST Python [restituito da ast.parse()].Elaborazione AST Python

So che questo è un AST di un metodo di classe.

Come trovo tutte le chiamate ad altri metodi della stessa classe?

Fondamentalmente, voglio raccogliere qualcosa come:

['foo', 'bar'] 

per un frammento di codice come:

def baz(self): # this is a class method 
    '''baz docstring''' 
    self.foo() + self.bar() 

Ho bisogno di una funzione che accetterà un AST e restituirà la lista di altri metodi [nomi di metodo come stringhe] della classe che viene invocata all'interno di un metodo della stessa classe.

risposta

16

L'approccio generale è quello di creare una sottoclasse ast.NodeVisitor:

>>> class VisitCalls(ast.NodeVisitor): 
... def visit_Call(self, what): 
...  if what.func.value.id == 'self': 
...  print what.func.attr 
... 
>>> f='''def x(self): 
... return self.bar() + self.baz() 
... ''' 
>>> xx = ast.parse(f) 
>>> VisitCalls().visit(xx) 
bar 
baz 

Tuttavia, questo sarà solo prendere "immediato" chiamate a self.something. Nel caso generale potresti avere ad es. somelist.append(self.blah) e poi molto più avanti nel codice somelist[i + j](): il problema di determinare se quest'ultimo è una chiamata a self.blah o ad un altro chiamabile che non ha nulla a che fare con i metodi dell'istanza corrente è Turing-completo (gergo CS per "completamente insolubile in il caso generale ", molto simile a un matematico potrebbe dire" NP-difficile ";-).

Ma se tutto ciò che serve è risolvere il semplice caso di "chiamata immediata", sei a posto ;-).

+0

Mille grazie per i commenti che descrivono la complessità del caso generale. –