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」、および引数値と戻り値を含む「Call」オブジェクトをインスタンス化します
  • リフレクションを使用して、それを (直接的または間接的に) 呼び出した最も近い同様に装飾された関数を検索します。つまり、@Tracked ではないため、g() への呼び出しを渡します。
  • 上記の「Call」オブジェクトを呼び出し元の「Call」オブジェクトの「子」リストに追加するか、適切な呼び出し元が見つからない場合はグローバル リスト 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」、および引数値と戻り値を含む「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

リフレクションを使用して、それを (直接的または間接的に) 呼び出した最も近い同様に装飾された関数を検索します。つまり、@Tracked ではないため、g() への呼び出しを渡します。

tracebackここで役に立ちます

上記の「Call」オブジェクトを呼び出し元の「Call」オブジェクトの「子」リストに追加するか、適切な呼び出し元が見つからない場合はグローバル リスト 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)

ただし、トレースバックには呼び出しパラメーターが表示されませんが、他のトレースバックがここで役立つことに同意することは可能です。

于 2013-03-19T07:06:20.937 に答える