1

鉴于:

G = []

@Track
def f(x):
  a = g(x)
  b = h(x + 2)
  return a + b

def g(x)
  for n in range(2):
    i(x + n)

@Track
def h(x):
  return j(x) + 9

@Track
def i(x):
  return x + 10

@Track
def j(x):
  return 0

是否可以为 f、h、i、j 编写和应用装饰器轨道,它将在每次调用 f、h、i 和 j 时:

  • 实例化一个包含函数名称“f”、“h”、“i”以及 arg 和返回值的“Call”对象
  • 使用反射来搜索最近调用它的类似装饰的函数(直接或间接),即它会将调用传递给 g(),因为那不是 @Tracked。
  • 将上述 'Call' 对象附加到调用者的 'Call' 对象上的 'children' 列表中,如果没有找到合适的调用者,则附加到全局列表 G

对于代码:

f(3)
j(3)

这应该创建以下连接对象树:

G
 -- Call(name='f',args=..., return=...)
    -- Call(name='i',args=..., return=...)
    -- Call(name='i',args=..., return=...)
    -- Call(name='i',args=..., return=...)
    -- Call(name='h',args=..., return=...)
      -- Call(name='j', args=..., return=...)
 -- Call(name='j', args=..., return=...)

我被困在反射/遍历运行时堆栈帧部分。

谢谢!

4

2 回答 2

0

实例化一个包含函数名称“f”、“h”、“i”以及 arg 和返回值的“Call”对象

global_list_of_calls = defaultdict(list)

def Track(func):
    def _tracked(*args, **kwargs):
        res = func(*args, **kwargs)
        c = Call(func.__name__, args, kwargs, res)
        # do something with c, store it in a global container
        global_list_of_calls.append(c)
        return res
    return _tracked

使用反射来搜索最近调用它的类似装饰的函数(直接或间接),即它会将调用传递给 g(),因为那不是 @Tracked。

traceback在这里会有所帮助

将上述 'Call' 对象附加到调用者的 'Call' 对象上的 'children' 列表中,如果没有找到合适的调用者,则附加到全局列表 G

请记住,当您使用参数和返回值存储调用时,它们不会被垃圾收集并且您的内存会增长。此外,如果您存储可变对象(例如,列表),您稍后看到的Call可能与Call创建时的不同

于 2013-03-19T06:45:18.457 回答
0

形式上,结果是这样的

stack=[]
shift=0
def Track(func):
    def wrapper(*args, **kwargs):
        global shift
        stack.append([])
        el=stack[-1]
        el.append('%s -- call(name=%s,args=%s,kwargs=%s)' % ('    '*shift,func.__name__,args, kwargs))
        shift+=1
        res = func(*args, **kwargs)
        shift-=1
        el[0]+='return=%s)' % res
        return res
    return wrapper

对于打印:

for i in stack: print i[0]

显示

 -- call(name=f,args=(3,),kwargs={})return=10)
     -- call(name=i,args=(3,),kwargs={})return=13)
     -- call(name=i,args=(4,),kwargs={})return=14)
     -- call(name=h,args=(5,),kwargs={})return=9)
         -- call(name=j,args=(5,),kwargs={})return=0)
 -- call(name=j,args=(3,),kwargs={})return=0)

但是有可能同意其他的traceback在这里会有帮助,虽然traceback没有显示调用参数

于 2013-03-19T07:06:20.937 回答