문제

이 코드를 가지고 있습니다 :

import inspect
import ast

def func(foo):
    return foo.bar - foo.baz

s = inspect.getsource(func)
xx = ast.parse(s)

class VisitCalls(ast.NodeVisitor):
    def visit_Name(self, what):
        if what.id == 'foo':
            print ast.dump(what.ctx)

VisitCalls().visit(xx)
.

함수 'func'에서 추출하고 싶습니다 :

['foo.bar', 'foo.baz']
.

또는 같은 것 :

(('foo', 'bar'), ('foo', 'baz))
.

편집

왜 내가이 일을해야한다고 생각하는지 설명하기위한 일부 배경

Trivial Python 함수의 코드를 스프레드 시트 수식으로 변환하고자합니다.

로 변환해야합니다 :

foo.bar - foo.baz
.

to :

=A1-B1
.

샘플 스프레드 시트 http://img441.imageshack.us/img441/1451/84516405. PNG

** 다시 편집 *

내가 지금까지 가지고있는 것.

출력 이하의 프로그램 :

('A1', 5)
('B1', 3)
('C1', '= A1 - B1')
.

코드 :

import ast, inspect
import codegen # by Armin Ronacher
from collections import OrderedDict

class SpreadSheetFormulaTransformer(ast.NodeTransformer):
    def __init__(self, sym):
        self.sym = sym
    def visit_Attribute(self, node):
        name = self.sym[id(eval(codegen.to_source(node)))]
        return ast.Name(id=name, ctx=ast.Load())

def create(**kwargs):
    class Foo(object): pass
    x = Foo()
    x.__dict__.update(kwargs)
    return x

def register(x,y):
    cell[y] = x
    sym[id(x)] = y

def func(foo):
    return foo.bar - foo.baz

foo = create(bar=5, baz=3)
cell = OrderedDict()
sym = {}

register(foo.bar, 'A1')
register(foo.baz, 'B1')

source = inspect.getsource(func)
tree = ast.parse(source)
guts = tree.body[0].body[0].value
SpreadSheetFormulaTransformer(sym).visit(guts)

code = '= ' + codegen.to_source(guts)
cell['C1'] = code

for x in cell.iteritems():
    print x
.

여기에 몇 가지 자원을 찾았습니다. r> "NoReferRer"> 파이썬 내부 : Python ASTS와 함께 일하고 있습니다 .

도움이 되었습니까?

해결책

import ast, inspect
import codegen # by Armin Ronacher

def func(foo):
    return foo.bar - foo.baz

names = []

class CollectAttributes(ast.NodeVisitor):
    def visit_Attribute(self, node):
        names.append(codegen.to_source(node))

source = inspect.getsource(func)

tree = ast.parse(source)
guts = tree.body[0].body[0].value
CollectAttributes().visit(guts)
print names
.

출력 :

['foo.bar', 'foo.baz']
.

다른 팁

나는 당신이 퇴직 해야하는 이유를 확신 할 수 없으며, 모든 이름과 점을 함수의 모든 이름과 도트를 얻을 수있는 매우 조잡한 방법은

import inspect
import parser
import symbol
import token
import pprint

def func(foo):
    return foo.bar - foo.baz

s = inspect.getsource(func)
st = parser.suite(s)

def search(st):
    if not isinstance(st, list):
        return
    if st[0] in [token.NAME, token.DOT]:
        print st[1],
    else:
        for s in st[1:]:
            search(s)

search(parser.ast2list(st))
.

출력 :

def func foo return foo . bar foo . baz
.

는 구문 트리를보다 우아하게 읽을 수 있습니다, 나는 Python 2.5

에 있기 때문에 AST 모듈 대신 파서를 사용하고 있습니다.

나는 아직 새로운 AST 모듈을 사용하지 않았지만 이전 컴파일러를 사용하는 코드를 사용하여 유사한 것을 얻기 위해

    def visitGetattr(self, node):
        full_name = [node.attrname]
        parent = node.expr
        while isinstance(parent, compiler.ast.Getattr):
            full_name.append(parent.attrname)
            parent = parent.expr
        if isinstance(parent, compiler.ast.Name):
            full_name.append(parent.name)
            full_name = ".".join(reversed(full_name))
            # do something with full_name
        for c in node.getChildNodes():
            self.visit(c)
.

코드는 약간의 것으로, 나는 부주의 한 벌레를 도입했을 것입니다.이것이 당신에게 일반적인 아이디어를 제공하기를 바랍니다. 이름과 getAttr 노드를 방문하고 점선 이름을 구축해야하며 모든 중간 값 (예 : 'foo'및 'foo.bar')을 볼 수있는 사실을 다룹니다.).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top