简体   繁体   English

如何使用ast评估内置function使用python?

[英]How to use ast to evaluate built-in function using python?

>>> list("abc")
['a', 'b', 'c']
>>> list = 42
>>> list("xyz")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable

How do i find such bugs if one has accidentally assigned values to class-names and function definitions?如果不小心将值分配给类名和 function 定义,我如何找到此类错误? I wanted to use AST but not really sure how do i do it?我想使用 AST 但不确定我该怎么做?

One approach is to extract ast nodes for constructs that could contain builtin shadowing;一种方法是为可能包含内置阴影的构造提取ast节点; for example, assignments, function signatures, for-loops, and comprehensions, and then check if any target names belonging to these ast objects are builtins:例如,赋值、function 签名、for 循环和理解,然后检查属于这些ast对象的任何目标名称是否是内置的:

import warnings
import builtins, ast
def extract_names(node):
  if isinstance(node, ast.Name):
     yield node.id
  elif isinstance(node, ast.arg):
     yield node.arg
  elif isinstance(node, list):
     for i in node: yield from extract_names(i)
  else:
     for i in getattr(node, '_fields', []): yield from extract_names(getattr(node, i))

def log_shadowing(node, names):
   for i in names:
      if i in dir(builtins):
         warnings.warn(f"On line {node.lineno}: shadowing of '{i}'")

def check_node(node):
   if isinstance(node, ast.Assign):
      log_shadowing(node, extract_names(node.targets))
   if isinstance(node, ast.FunctionDef):
      log_shadowing(node, [node.name, *extract_names(node.args)])
   if isinstance(node, ast.For):
      log_shadowing(node, extract_names(node.target))
   if isinstance(node, (ast.ListComp, ast.SetComp, ast.DictComp)):
      for i in node.generators:
         log_shadowing(node, extract_names(i.target)) 

sample = """ 
list = 10
def f(a, b, dict, c):
   pass

for set in range(10):
   pass

r = [next for next in range(10)]
"""
for i in ast.walk(ast.parse(sample)):
   check_node(i)

Output: Output:

<stdin>:4: UserWarning: On line 2: shadowing of 'list'
<stdin>:4: UserWarning: On line 3: shadowing of 'dict'
<stdin>:4: UserWarning: On line 6: shadowing of 'set'
<stdin>:4: UserWarning: On line 9: shadowing of 'next'

you need to compare list to its original value, which can be found in the module builtins:您需要将列表与其原始值进行比较,这可以在内置模块中找到:

import builtins
print(builtins.list == list) # true
list = 42
print(builtins.list == list) # false

The better thing is to just avoid assigning to built-in functions.更好的办法是避免分配给内置函数。 A good code editor will make built-in functions a different color一个好的代码编辑器会让内置函数有不同的颜色

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM