¿Cómo encontrar el nombre de una variable que se pasó a una función?

En C / C ++, a menudo he encontrado útil mientras depuraba para definir una macro, digamos ECHO(x) , que imprime el nombre de la variable y su valor (es decir, ECHO(variable) puede imprimir la variable 7 ). Puede obtener el nombre de la variable en una macro usando el operador # “clasificación” como se describe aquí . ¿Hay alguna manera de hacer esto en Python?

En otras palabras, me gustaría una función.

 def echo(x): #magic goes here 

el cual, si es llamado como foo=7; echo(foo) foo=7; echo(foo) (o foo=7; echo('foo') , tal vez), imprimiría foo 7 . Me doy cuenta de que es trivial hacer esto si le paso tanto la variable como su nombre a la función, pero uso mucho las funciones de este tipo al depurar, y la repetición siempre me irrita.

No es realmente una solución, pero puede ser útil (de todas formas tienes un echo('foo') en cuestión):

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

ACTUALIZACIÓN: Solución para echo(foo) con 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)) 

Salida:

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

Tiene la llamada más pequeña, pero es sensible a las nuevas líneas, por ejemplo:

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

Se imprimirá:

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

Consulte también: https://stackoverflow.com/a/2387854/16361

Tenga en cuenta que esto puede causar problemas de GC:

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

También apagará a las personas que se hayan quemado al jugar con los marcos y puede dejar un mal sabor de boca. Pero funcionará.

Aquí hay una solución que tiene que escribir un poco más para llamarlo. Se basa en la función incorporada locals :

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

También es posible un echo con la semántica que mencionó, utilizando el módulo de inspección . Sin embargo, lea las advertencias en la documentación de inspeccionar. Este es un truco feo no portátil (no funciona en todas las implementaciones de Python). Asegúrate de usarlo solo para la depuración.

La idea es mirar en los locales de la función de llamada. El módulo de inspección permite solo eso: las llamadas están representadas por objetos de ttwig vinculados entre sí por el atributo f_back . Las variables locales y globales de cada cuadro están disponibles (también hay elementos incorporados, pero es poco probable que necesite imprimirlos).

Es posible que desee eliminar explícitamente cualquier objeto de marco de referencia para evitar ciclos de referencia, como se explica en la documentación de inspección , pero esto no es estrictamente necesario, ya que la recolección de basura los liberará tarde o temprano.

 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')