Entry
I want to print debugging info but get tired of saying print( 'a: ', a). How can I automatically get the name of a variable I passed?
Introspective: How to find out the names of variables and objects
How can I find all the names a given thing is known under?
Dec 15th, 2000 08:34
Wolfgang Lipp, Luiz Henrique de Figueiredo (on the lua list), Nathan Wallace (http://www.e-gineer.com) (on python.faqts.com)
import sys
# thx to Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br>
# and Nathan Wallace (http://www.e-gineer.com)
# for pointing out this solution in Lua and Python
# -wl
# names()
# + thing thing whose names we are looking for
# | + if true, return all the names of <thing>;
# | | otherwise, only the first name found
# | | + if true, exclude uninteresting
# | | | internal names (as given in
# | | | the tuple)
# | | |
def names( thing, all = 1, exclude_internals = 1 ):
"""
The function names( thing ) will return a list containing
all the names a thing can be accessed under, or None, if
it is an anonymous instance. It will never return an empty
list; all names in the list will be unique.
See the source for refinements. In particular, it is
possible to ask for names( thing, all = 0 ), which will
either return one *string* containing the first name found
while searching, or None.
An extension would be to include the module names with the
results, preferrably in the form 'module.name'. Later.
wolf <castor@snafu.de>
"""
# Add <name> to dictionary <names>, conditionally
# excluding it in case it is None or on the exclusion
# list.
# Return 1 if name was added to dictionary, 0 otherwise.
def add( names, name, exclude_internals = 1 ):
if exclude_internals:
if name in (
'S_IROTH', 'ST_UID', 'P_DETACH',
'SIGILL', 'R_OK'
):
name = None
if name != None:
names[ name ] = 1 # or any other dummy value
return 1
else:
return 0
R = {}
# Look for the __name__ attribute and conditionally
# add it to the names collection; in case thing has
# a __name__, it is not to be excluded and we
# don't want to have all the names (ie if all = 0),
# then that's it. Otherwise, proceed below.
#
# PS. put the if clause onto a single line,
# that is much clearer.
if add(
R,
getattr( thing, '__name__', None ),
exclude_internals
) and not all:
return R.keys()[0]
# Go through all the modules and check all the
# items recorded there.
# If item is identical to thing, then try to
# add that name to the names collection. As
# above, in case thing has a __name__, it is
# not to be excluded and we don't want to have
# all the names (ie if all = 0), then that's
# it. Otherwise, proceed with the
# subsequent items and the subsequent modules.
for module in sys.modules.values():
for name, val in module.__dict__.items():
if val is thing:
if add( R, name, exclude_internals ) and not all:
return R.keys()[0]
# Do not return an empty list of keys of the
# names collection, return plain None instead.
if len( R.keys() ):
return R.keys()
else:
return None
if __name__ == '__main__':
sin = sys.stdin
mymod = sys
print names( sys.stdin )
# ['stdin', '__stdin__', 'sin']
print names( sin )
# ['stdin', '__stdin__', 'sin']
print names( sys )
# ['mymod', 'sys']
print names( mymod )
# ['mymod', 'sys']
print names( names )
# ['names']
print names( lambda x: x+1 )
# ['<lambda>']
print '-----------------------'
a = 4
print names( a, exclude_internals = 0 )
# ['P_DETACH', 'S_IROTH', 'R_OK', 'SIGILL', 'ST_UID', 'a']
print names( a )
# ['a']
print names( a, all = 0 )
# a
print '-----------------------'
b = 4
c = 4
a = b * 9 + 4
print names( a, exclude_internals = 0 )
# ['a']
print names( b, exclude_internals = 0 )
# ['S_IROTH', 'ST_UID', 'P_DETACH', 'c', 'b',
# 'SIGILL', 'R_OK']
print names( c, exclude_internals = 0 )
# ['S_IROTH', 'ST_UID', 'P_DETACH', 'c', 'b',
# 'SIGILL', 'R_OK']
print names( a )
# ['a']
print names( b )
# ['b', 'c']
print names( c )
# ['b', 'c']
print '-----------------------'
class X:
pass
x = X()
print names( X ) # ['X']
print names( X() ) # None
print names( x ) # ['x']