是的,我可以手动在每个方法的定义代码的开头添加一行print("call xxx")
。但这似乎有点愚蠢。
例如:
class Test():
def a(self):
return self.b()
def b(self):
return self.c()
def c(self):
return
当你用X
处理Test
,然后调用Test().a()
时,控制台会打印一些东西像:
call -> a
call -> b
call -> c
这样就可以看到方法a
是如何调用其他方法的,这有助于理解一些复杂类的逻辑(比如Django的ListView
)
首先,我使用元类来制作X
,即:
import functools
def print_info(func):
@functools.wraps(func)
def magic(*args,**kwargs):
print('call -> %s'%func.__name__)
return func(*args,**kwargs)
return magic
class BlackMeta(type):
def __new__(cls, name, parents, attrs):
new_attrs={}
for k,v in attrs.items():
if callable(v):
new_attrs[k] = print_info(v)
else:
new_attrs[k] = v
return type.__new__(cls, name, parents, new_attrs)
class Test(metaclass=BlackMeta):
def a(self):
return self.b()
def b(self):
return self.c()
def c(self):
return
它有效。但是当我将 BlackMeta
添加到 DetailView
的子类并调用方法 get
时,出现错误:
所以我放弃了,来这里寻求帮助。不一定是元类,任何可以显示方法调用顺序的东西都可以。谢谢。
最佳答案
您可以使用sys.settrace
来注册一个函数,每当调用函数时都会调用该函数,如下所示:
import sys
def trace(frame, event, arg):
if event == 'call':
print("%s (%s line %d)" % (frame.f_code.co_name, frame.f_code.co_filename, frame.f_lineno))
return trace
class Test():
def a(self):
return self.b()
def b(self):
return self.c()
def c(self):
return
def do_stuff():
t = Test()
t.a()
sys.settrace(trace)
do_stuff()
输出:
do_stuff (x.py line 16)
a (x.py line 9)
b (x.py line 11)
c (x.py line 13)
只要在任何地方调用任何函数,您的跟踪函数就会被调用,所以天真的
这里的版本将在一个不平凡的程序中产生大量输出!您只需要在相关时打印输出,例如。通过查看frame.f_code.co_filename
。
关于Python 3 有什么东西可以打印类方法调用的顺序吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23184401/