2016-05-13 8 views
0

Целью является определение встроенной функции, например eval(), в некотором коде.Как найти/определить, используется ли встроенная функция в Python AST?

def foo(a): 
    eval('a = 2') 

Я попытался следующий подход:

ex_ast = ast.parse(inspect.getsource(foo)) 

for node in ast.walk(ex_ast): 
if isinstance(node, ast.FunctionDef): 
    print(node.name) 

Имя функции foo печатается как выход.

Я знаю, что встроенные функции не имеют конструкторов. Они находятся в модуле type. Таким образом, 1 подход будет использовать types.FunctionType в вызове isinstance.

Но так как я использую узлы AST. Они не могут быть преобразованы обратно в код. Я должен проверить для каждого узла, если они types.FunctionType:

for node in ast.walk(ex_ast): 
    if isinstance(node, ast.FunctionType): 
     print(node.name) 

Я получил эти ошибки:

AttributeError: module 'ast' has no attribute 'FunctionType' 

Как я должен правильно определить, если конкретный Buildin функция используется в коде? Благодаря!

+0

«Я знаю, что встроенные функции не имеют конструкторов. Они находятся в модуле' type'. - вы серьезно неправильно поняли здесь. – user2357112

+0

@ user2357112 Я узнал, что отсюда [ссылка] (http://stackoverflow.com/questions/624926/how-to-detect-whether-a-python-variable-is-a-function), можете ли вы объяснить, что дальше если вы уверены? благодаря! – HayleyL

+0

Этот ответ говорит о том, что нет встроенной функции, которую вы вызываете для создания функций, и что объект типа, представляющий тип функций, доступен в модуле 'types'. Вы взяли слова и создали похожие, но неправильные предложения из них. – user2357112

ответ

1

Когда вы пишете eval(whatever) в своем коде, eval просматривается обычным глобальным поиском переменных. Вы должны искать ast.Name узел, представляющий собой использование имени переменной eval:

for node in ast.walk(ex_ast): 
    if isinstance(node, ast.Name) and node.id == 'eval': 
     # Found it. 

Поскольку у вас есть реальный объект функции, а не только исходный код, вы также можете проверить переменные, ТЕНЬ встроенный в чуть более надежный способ, чем если бы вы только что источник работы функции:

if ('eval' in foo.__code__.co_varnames  # local variable 
    or 'eval' in foo.__code__.co_cellvars # local variable used by nested function 
    or 'eval' in foo.__code__.co_freevars # local variable from enclosing function 
    or 'eval' in foo.__globals__):   # global variable 
    # Some variable is shadowing the built-in. 

Это не будет ловить глобал добавлен после проверки, и он не будет делать ничего о доступах к встроенному под другим именем (например, x = eval; x('whatever')). Стоит ли вам решать это.

+0

@ Kupiakos: Действительно, это должно быть. Typo исправлено. – user2357112

+0

Спасибо, что решил мой вопрос! @Kupiakos, который является 'и node.id', спасибо за указание! – HayleyL

+0

Это предполагает, что ничего не затеняет встроенный. Учитывая, сколько людей пишут 'list = []' в своем коде, это решение является неполным. –