如何在被调用的方法中获得调用者的方法名?
假设我有两个方法:
def method1(self):
...
a = A.method2()
def method2(self):
...
如果我不想为method1做任何改变,如何获得调用者的名字(在这个例子中,名字是method1)在method2?
如何在被调用的方法中获得调用者的方法名?
假设我有两个方法:
def method1(self):
...
a = A.method2()
def method2(self):
...
如果我不想为method1做任何改变,如何获得调用者的名字(在这个例子中,名字是method1)在method2?
当前回答
上面的东西混合在一起。但这是我的尝试。
def print_caller_name(stack_size=3):
def wrapper(fn):
def inner(*args, **kwargs):
import inspect
stack = inspect.stack()
modules = [(index, inspect.getmodule(stack[index][0]))
for index in reversed(range(1, stack_size))]
module_name_lengths = [len(module.__name__)
for _, module in modules]
s = '{index:>5} : {module:^%i} : {name}' % (max(module_name_lengths) + 4)
callers = ['',
s.format(index='level', module='module', name='name'),
'-' * 50]
for index, module in modules:
callers.append(s.format(index=index,
module=module.__name__,
name=stack[index][3]))
callers.append(s.format(index=0,
module=fn.__module__,
name=fn.__name__))
callers.append('')
print('\n'.join(callers))
fn(*args, **kwargs)
return inner
return wrapper
Use:
@print_caller_name(4)
def foo():
return 'foobar'
def bar():
return foo()
def baz():
return bar()
def fizz():
return baz()
fizz()
输出是
level : module : name
--------------------------------------------------
3 : None : fizz
2 : None : baz
1 : None : bar
0 : __main__ : foo
其他回答
代码:
#!/usr/bin/env python
import inspect
called=lambda: inspect.stack()[1][3]
def caller1():
print "inside: ",called()
def caller2():
print "inside: ",called()
if __name__=='__main__':
caller1()
caller2()
输出:
shahid@shahid-VirtualBox:~/Documents$ python test_func.py
inside: caller1
inside: caller2
shahid@shahid-VirtualBox:~/Documents$
我将使用inspect.currentframe().f_back.f_code.co_name。它的用法在之前的回答中没有涉及,主要有三种类型:
一些先前的答案使用inspect。堆栈,但它是众所周知的太慢。 一些先前的回答使用sys。_getframe是一个内部私有函数,因为它有前导下划线,所以不鼓励使用它。 一个先前的答案使用inspect.getouterframes(inspect.currentframe(), 2)[1][3],但它完全不清楚[1][3]正在访问什么。
import inspect
from types import FrameType
from typing import cast
def demo_the_caller_name() -> str:
"""Return the calling function's name."""
# Ref: https://stackoverflow.com/a/57712700/
return cast(FrameType, cast(FrameType, inspect.currentframe()).f_back).f_code.co_name
if __name__ == '__main__':
def _test_caller_name() -> None:
assert demo_the_caller_name() == '_test_caller_name'
_test_caller_name()
注意cast(FrameType, frame)是用来满足mypy的。
致谢:回复请留言1313e。
我找到了一种方法,如果你要跨越类,并且想要方法所属的类和方法。这需要一些提取工作,但它是有意义的。这在Python 2.7.13中有效。
import inspect, os
class ClassOne:
def method1(self):
classtwoObj.method2()
class ClassTwo:
def method2(self):
curframe = inspect.currentframe()
calframe = inspect.getouterframes(curframe, 4)
print '\nI was called from', calframe[1][3], \
'in', calframe[1][4][0][6: -2]
# create objects to access class methods
classoneObj = ClassOne()
classtwoObj = ClassTwo()
# start the program
os.system('cls')
classoneObj.method1()
嘿,伙计,我曾经为我的应用程序做了3个没有插件的方法,也许这可以帮助你,它对我有用,所以可能对你也有用。
def method_1(a=""):
if a == "method_2":
print("method_2")
if a == "method_3":
print("method_3")
def method_2():
method_1("method_2")
def method_3():
method_1("method_3")
method_2()
上面的东西混合在一起。但这是我的尝试。
def print_caller_name(stack_size=3):
def wrapper(fn):
def inner(*args, **kwargs):
import inspect
stack = inspect.stack()
modules = [(index, inspect.getmodule(stack[index][0]))
for index in reversed(range(1, stack_size))]
module_name_lengths = [len(module.__name__)
for _, module in modules]
s = '{index:>5} : {module:^%i} : {name}' % (max(module_name_lengths) + 4)
callers = ['',
s.format(index='level', module='module', name='name'),
'-' * 50]
for index, module in modules:
callers.append(s.format(index=index,
module=module.__name__,
name=stack[index][3]))
callers.append(s.format(index=0,
module=fn.__module__,
name=fn.__name__))
callers.append('')
print('\n'.join(callers))
fn(*args, **kwargs)
return inner
return wrapper
Use:
@print_caller_name(4)
def foo():
return 'foobar'
def bar():
return foo()
def baz():
return bar()
def fizz():
return baz()
fizz()
输出是
level : module : name
--------------------------------------------------
3 : None : fizz
2 : None : baz
1 : None : bar
0 : __main__ : foo