扩展ast.ast

2024-03-29 08:14:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在编写一个Python工具,它遍历AST来提取一些数据。 为了提高其可用性,我想扩展ast.AST类,以便基于它的每个节点都具有相同的功能,例如获取父节点、子节点、兄弟节点等

在Python3.9+上,我能够将其他属性、方法和缓存属性直接附加到ast.AST

def _attach_to(cls, name=None):
    def decorator(func):
        func_name = name or func.__name__
        cached = cached_property(func)
        setattr(cls, func_name, cached)
        # see https://bugs.python.org/issue38524
        cached.__set_name__(cls, func_name)  # noqa: WPS609
        return func
    return decorator

但是在我愿意支持的Python 3.8上,我不能将其他东西附加到ast.AST这是一个内置的:

TypeError: can't set attributes of built-in/extension type '_ast.AST'

所以我探索了不同的东西:

  • 使用一类mine修补^{cd1>}并使用修补函数(如^{cd5>}:它似乎不会影响已从原始^{{cd1>}继承的子类
  • 修补ast.AST.__mro____mro__是只读的
  • 修补ast.AST.__bases__:无法设置内置的属性
  • 在子类上迭代并在其__bases__中将ast.AST更改为我自己的ExtendedAST(从ast.AST继承):抱怨对象布局不同

有没有一种方法可以动态地向内置类添加属性/方法/属性


1条回答
网友
1楼 · 发布于 2024-03-29 08:14:21

我最终发现了一些有用的东西:我声明了一个ExtendedAST类,但没有将其作为ast.AST的子类,而是将其保留为“mixin”,并将其附加到所有不同节点类的__bases__

for name, member in inspect.getmembers(ast):
    if name != "AST" and inspect.isclass(member):
        if ast.AST in member.__bases__:
            new_bases = list(member.__bases__)
            new_bases.append(ExtendedAST)
            member.__bases__ = tuple(new_bases)

相关问题 更多 >