如何找到实例创建相关的AST赋值节点?

How to find the AST assignment node related to the instance creation?

如何select对象实例化相关的赋值节点?

例如:

class A:
    
    def __init__(self, param):
        self.param = param
        curframe = inspect.currentframe().f_back
        nodes = ast.parse(inspect.getsource(curframe))
        print(nodes.body)
        
        
a = A('test')
b = 'another assign'

>>> [<_ast.ClassDef object at 0x7fdffd72f400>, <_ast.Assign object at 0x7fdffd719a60>,
>>> <_ast.Assign object at 0x7fdffd719ee0>]

我想select只分配与A实例化相关的ast对象。例如,如何只打印特定的ast.Assign对象?

我试过这种方法,但是当有两个分配给同一个 class:

时,它无法单数化
class A:
    
    def __init__(self, param):
        self.param = param
        curframe = inspect.currentframe().f_back
        nodes = ast.parse(inspect.getsource(curframe))
                
        for node in nodes.body:
            try:
                if node.value.func.id == self.__class__.__name__:
                    print(ast.dump(node))
            except Exception:
                pass
        
        
a = A('test')
b = 'another assign'
c = A('another test')

>>> Assign(targets=[Name(id='a', ctx=Store())], value=Call(func=Name(id='A', ctx=Load()),
>>> args=[Constant(value='test', kind=None)], keywords=[]), type_comment=None)
>>> Assign(targets=[Name(id='c', ctx=Store())], value=Call(func=Name(id='A', ctx=Load()), 
>>> args=[Constant(value='another test', kind=None)], keywords=[]), type_comment=None)
>>> Assign(targets=[Name(id='a', ctx=Store())], value=Call(func=Name(id='A', ctx=Load()), 
>>> args=[Constant(value='test', kind=None)], keywords=[]), type_comment=None)
>>> Assign(targets=[Name(id='c', ctx=Store())], value=Call(func=Name(id='A', ctx=Load()), 
>>> args=[Constant(value='another test', kind=None)], keywords=[]), type_comment=None)

我认为还有另一种简单的方法可以实现这一点。有人知道更好的方法吗?

提前致谢。

因为你有两个 class A 对象的实例化,代码使得 与正在执行的实际行没有区别,两者都赋值 语句被打印两次。

通过保留self.nodes稍微更改代码(便于调试) 并在外框内添加当前行,我们可以确保 实际执行的任务只打印出来。

import ast
import inspect

class A:
    def __init__(self, param):
        self.param = param
        curframe = inspect.currentframe().f_back
        curline = inspect.currentframe().f_back.f_lineno
        self.nodes = ast.parse(inspect.getsource(curframe))

        for node in self.nodes.body:
            if node.lineno == curline:
                print(ast.dump(node))

a = A('test')
b = 'another assign'
c = A('another test')

输出(为演示重新格式化):

# Assign(targets=[Name(id='a', ctx=Store())],
         value=Call(func=Name(id='A', ctx=Load()),
         args=[Constant(value='test')], keywords=[]))
# Assign(targets=[Name(id='c', ctx=Store())],
         value=Call(func=Name(id='A', ctx=Load()),
         args=[Constant(value='another test')], keywords=[]))