Find the name of a Python variable that was passed to a function

匿名 (未验证) 提交于 2019-12-03 01:40:02

问题:

In C/C++, I have often found it useful while debugging to define a macro, say ECHO(x), that prints out the variable name and its value (i.e. ECHO(variable) might print variable 7). You can get the variable name in a macro using the 'stringification' operator # as described here. Is there a way of doing this in Python?

In other words, I would like a function

def echo(x):     #magic goes here 

which, if called as foo=7; echo(foo) (or foo=7; echo('foo'), maybe), would print out foo 7. I realise it is trivial to do this if I pass both the variable and its name to the function, but I use functions like this a lot while debugging, and the repetition always ends up irritating me.

回答1:

Not really solution, but may be handy (anyway you have echo('foo') in question):

def echo(**kwargs):     for name, value in kwargs.items():         print name, value  foo = 7 echo(foo=foo) 

UPDATE: Solution for echo(foo) with inspect

import inspect import re  def echo(arg):     frame = inspect.currentframe()     try:         context = inspect.getframeinfo(frame.f_back).code_context         caller_lines = ''.join([line.strip() for line in context])         m = re.search(r'echo\s*\((.+?)\)$', caller_lines)         if m:             caller_lines = m.group(1)         print caller_lines, arg     finally:         del frame  foo = 7 bar = 3 baz = 11 echo(foo) echo(foo + bar) echo((foo + bar)*baz/(bar+foo)) 

Output:

foo 7 foo + bar 10 (foo + bar)*baz/(bar+foo) 11 

It has the smallest call, but it's sensitive to newlines, e.g.:

echo((foo + bar)*       baz/(bar+foo)) 

Will print:

baz/(bar+foo)) 11 


回答2:

def echo(x):     import inspect     print "{0}: {1}".format(x, inspect.stack()[1][0].f_locals[x]) y = 123 echo('y') # 'y: 123' 

See also: https://stackoverflow.com/a/2387854/16361

Note that this can cause GC issues:

http://docs.python.org/library/inspect.html#the-interpreter-stack

It will also turn off people who have been burned by messing with frames, and may leave a bad taste in your mouth. But it will work.



回答3:

Here's a solution that has you type a bit more to call it. It relies on the locals built-in function:

def print_key(dictionary, key):     print key, '=', dictionary[key]   foo = 7 print_key(locals(), 'foo') 

An echo with the semantics you mentioned is also possible, using the inspect module. However, do read the warnings in inspect's documentation. This is an ugly non-portable hack (it doesn't work in all implementations of Python). Be sure to only use it for debugging.

The idea is to look into the locals of the calling function. The inspect module allows just that: calls are represented by frame objects linked together by the f_back attribute. Each frame's local and global variables are available (there are also builtins, but you're unlikely to need to print them).

You may want to explicitly delete any references frame objects to prevent reference cycles, as explained in inspect docs

import inspect  def echo(varname):     caller = inspect.currentframe().f_back     try:         value = caller.f_locals[varname]     except KeyError:         value = caller.f_globals[varname]     print varname, '=', value     del caller  foo = 7 echo('foo') 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!