例如:
def func(a):
# how to get the name "x"
x = 1
func(x)
如果我使用inspect
模块,我可以获得堆栈帧对象:
import inspect
def func(a):
print inspect.stack()
出:
[
(<frame object at 0x7fb973c7a988>, 'ts.py', 9, 'func', [' stack = inspect.stack()\n'], 0)
(<frame object at 0x7fb973d74c20>, 'ts.py', 18, '<module>', ['func(x)\n'], 0)
]
或使用inspect.currentframe()
我可以获取当前帧。
但是我只能通过检查函数对象获得名称"a"
。
使用inspect.stack
我可以获得调用堆栈:"['func(x)\n']"
,
如何通过解析"x"
来调用func
来获取实际参数的名称("['func(x)\n']"
)?
如果我致电func(x)
,我会得到"x"
如果我致电func(y)
,我会得到"y"
一个例子:
def func(a):
# Add 1 to acttual parameter
...
x = 1
func(x)
print x # x expected to 2
y = 2
func(y)
print y # y expected to 3
答案 0 :(得分:3)
查看您的评论解释,您尝试这样做的原因是:
因为我想在C ++中推动参考参数
你做不到。在python中,所有内容都按值传递,但该值是对您传递的对象的引用。现在,如果该对象是可变的(如列表),您可以修改它,但如果它是不可变的,则创建并设置一个新对象。在您的代码示例中,x
是int
,它是不可变的,因此如果您想更改x
的值,只需从您调用的函数返回其新值: / p>
def func(a):
b = 5 * a
# ... some math
return b
x = 1
x = func(x)
那么如果你想返回多个值呢?使用tuple
!
def func(a, b):
a, b = 5 * b, 6 * a
# ...
return b, a
a, b = 2, 3
a, b = func(a, b)
答案 1 :(得分:1)
这在某种程度上是可行的 - 但在任何类型的真实代码中都是无用的。 你可以将它用于后院魔术:
只需像你正在那样检索调用stack_frame,
然后线性循环通过调用帧中可用的变量
引用您作为参数获得的同一对象的一个。变量在
f_locals
和f_globals
字典,它们是框架对象的属性。
当然,传递的参数可能不是以变量名开头的: 它可能是调用者中的常量,也可能是在字典或列表中。
无论哪种方式,正如@Nasser所说的那样:它不是Python的工作方式。对象存在于内存中,每个范围中的变量名只指向这些对象。否则这些名称本身毫无意义。
import inspect
from itertools import chain
def magic(x):
# note that in Python2, 'currentframe' could get a parameter
# to indicate which frame you want on the stack. Not so in Python3
fr = inspect.currentframe().f_back
for var_name, value in chain(fr.f_locals.items(), fr.f_globals.items()):
if value is x:
print ("The variable name in the caller context is {}".format(var_name))
def caler():
y = "My constant"
magic(y)
答案 2 :(得分:0)
使用列表作为参考
def func(a):
a[0] = a[0] + 1
x = [1]
func(x)
print x[0] # x expected to 2
y = [2]
func(y)
print y[0] # y expected to 3
答案 3 :(得分:-1)
这是我的最终解决方案。使用ast解析函数语句并获取args。:
import inspect
import re
import ast
def func(a,b,c):
stack = inspect.stack()
stack_pre = stack[1]
function_call_string = ';'.join( stack_pre[4] ).strip('\n')
ret = re.search(r'(%s[ ]*\(.*\))' % func.func_name, function_call_string)
striped_function_call_string = ret.group()
parser = ast.parse(striped_function_call_string)
frame = inspect.currentframe()
for arg in parser.body[0].value.args:
iter_frame = frame.f_back
while iter_frame:
if arg.id in iter_frame.f_locals:
iter_frame.f_locals[arg.id] += 1
break
iter_frame = iter_frame.f_back
x=1;y=2;z=3;func(x,y,z)
print x,y,z
输出:
2 3 4