问题
I mean to define a function print_echo
that replaces print
, such that in addition to printing the result of an expression it prints the expression itself.
If I simply pass the expression as a string and use eval
inside print_echo
, it will not know any variable local to the caller function.
My current code is
def print_echo( expr ) :
result = eval( expr )
print( expr + ' => ' + str( result ) + ' ' + str( type( result ) ) )
return
But when using
def my_func( params ) :
a = 2
print_echo( "a" )
I get (no surprise)
NameError: name 'a' is not defined
I mean to get
a => 2 <type 'int'>
I conceived two ways of working around this.
Use a Python like alternative for C preprocessor macros. Something like C Preprocessor Macro equivalent for Python
Pass all local variables to print_echo. Something like Passing all arguments of a function to another function
Since I find inconvenient aspects for each of the two, Is there any alternative to these?
Note that expr is a generic expression, not necessarily the name of a variable.
回答1:
eval() only takes the global namespace, and the namespace local to where it is called, into account.
In your case, you need the namespace of where print_echo
is called (i.e., the "parent" namespace of where eval
is called) as the local namespace, which you can get by using the inspect module and pass to eval
as an argument.
import inspect
def print_echo(expr):
outer_locals = inspect.currentframe().f_back.f_locals
result = eval(expr, globals(), outer_locals)
print(expr, '=>', result, type(result))
a = 2
print_echo('a')
def f():
b = 3
print_echo('b')
f()
Python 3 output:
a => 2 <class 'int'>
b => 3 <class 'int'>
回答2:
Important Note: There can be more error handling to this case. For more info, you can see inspect and explore it further. https://docs.python.org/2/library/inspect.html
import inspect
# NOTE: this only prints the local variables to the function
def print_echo( *expr ) :
frame = inspect.currentframe().f_back # see the previous frame and what all variable it's previous caller knows
values = inspect.getargvalues(frame)[3]
print values # just to understand what it is, remove it later
for e in expr:
try:
result = values[e]
except KeyError:
eval(e) # see the globally defined variables, if not found local to previous function.
print( str(e) + ' => ' + str( result ) + ' ' + str( type( result ) ) )
来源:https://stackoverflow.com/questions/52987211/print-expression-and-also-echo-it