Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Little Q: how to print a variable's name, not its value?

1,451 views
Skip to first unread message

stewart....@gmail.com

unread,
Mar 29, 2005, 1:06:44 AM3/29/05
to
No doubt I've overlooked something obvious, but here goes:

Let's say I assign a value to a var, e.g.:
myPlace = 'right here'
myTime = 'right now'

Now let's say I want to print out the two vars, along with their names.
I could easily do this:
print "myPlace = %s, myTime = %s" % (myPlace, myTime)

But that requires that I know in advance the name of the vars. What if
they are assigned dynamically. What I'm looking for is some method (
call it f() ) that allows me to do this:
print "%s = %s, %s = %s" % (f(myPlace), myPlace, f(myTime), myTime)

Any ideas?

repr() doesn't do it for me, nor ``.

thanks
Stewart in Calgary

Brian van den Broek

unread,
Mar 29, 2005, 1:53:54 AM3/29/05
to stewart....@gmail.com, pytho...@python.org
stewart....@gmail.com said unto the world upon 2005-03-29 01:06:

Use a dictionary instead of free floating variables to store your data.

Stewarts_data = { 'myPlace' : 'right here',
'myTime' : 'right now' }
for item in Stewarts_data.items():
print '%s = %s' %item

(There are likely even nicer ways -- for instance in Python 2.4 you
can use sorted() on the dictionary -- but this gets the idea across, I
hope.)

Best,

Brian vdB

Dan Bishop

unread,
Mar 29, 2005, 2:01:34 AM3/29/05
to
stewart....@gmail.com wrote:
> No doubt I've overlooked something obvious, but here goes:
>
> Let's say I assign a value to a var, e.g.:
> myPlace = 'right here'
> myTime = 'right now'
>
> Now let's say I want to print out the two vars, along with their
names.
> I could easily do this:
> print "myPlace = %s, myTime = %s" % (myPlace, myTime)
>
> But that requires that I know in advance the name of the vars. What
if
> they are assigned dynamically. What I'm looking for is some method (
> call it f() ) that allows me to do this:
> print "%s = %s, %s = %s" % (f(myPlace), myPlace, f(myTime), myTime)
>
> Any ideas?

Try something like this:

>>> def print_vars(vars_dict=None):
... if vars_dict is None:
... vars_dict = globals()
... for var, value in vars_dict.items():
... print '%s = %r' % (var, value)
...


>>> myPlace = 'right here'
>>> myTime = 'right now'

>>> print_vars()
print_vars = <function print_vars at 0x401e0d84>
__builtins__ = <module '__builtin__' (built-in)>
myTime = 'right now'
myPlace = 'right here'
__name__ = '__main__'
__doc__ = None

Christos TZOTZIOY

unread,
Mar 29, 2005, 6:12:55 AM3/29/05
to
On 28 Mar 2005 22:06:44 -0800, rumours say that
"stewart....@gmail.com" <stewart....@gmail.com> might have
written:

<snip complete article-- subject is enough>

Read about locals() and globals() in the Python documentation. These
provide the information you request (ie what names are bound to what
objects).
--
TZOTZIOY, I speak England very best.
"Be strict when sending and tolerant when receiving." (from RFC1958)
I really should keep that in mind when talking with people, actually...

Ron_Adam

unread,
Mar 29, 2005, 9:34:39 AM3/29/05
to
On 28 Mar 2005 23:01:34 -0800, "Dan Bishop" <dan...@yahoo.com> wrote:

>>>> def print_vars(vars_dict=None):
>... if vars_dict is None:
>... vars_dict = globals()
>... for var, value in vars_dict.items():
>... print '%s = %r' % (var, value)
>...
>>>> myPlace = 'right here'
>>>> myTime = 'right now'
>>>> print_vars()
>print_vars = <function print_vars at 0x401e0d84>
>__builtins__ = <module '__builtin__' (built-in)>
>myTime = 'right now'
>myPlace = 'right here'
>__name__ = '__main__'
>__doc__ = None


Fred = 5
John = 8
Winner = John

Both John and Winner are pointing to the literal '8'.

Mixing data and program code, ie.. variable names as data, is not a
good idea.

Dictionaries are one of pythons best features. ;)


Ron

Bill Mill

unread,
Mar 29, 2005, 11:23:45 AM3/29/05
to Ron_Adam, pytho...@python.org
On Tue, 29 Mar 2005 14:34:39 GMT, Ron_Adam <rad...@tampabay.rr.com> wrote:
> On 28 Mar 2005 23:01:34 -0800, "Dan Bishop" <dan...@yahoo.com> wrote:
>
> >>>> def print_vars(vars_dict=None):
> >... if vars_dict is None:
> >... vars_dict = globals()
> >... for var, value in vars_dict.items():
> >... print '%s = %r' % (var, value)
> >...
> >>>> myPlace = 'right here'
> >>>> myTime = 'right now'
> >>>> print_vars()
> >print_vars = <function print_vars at 0x401e0d84>
> >__builtins__ = <module '__builtin__' (built-in)>
> >myTime = 'right now'
> >myPlace = 'right here'
> >__name__ = '__main__'
> >__doc__ = None
>
> Fred = 5
> John = 8
> Winner = John
>
> Both John and Winner are pointing to the literal '8'.

ummm, yes, of course they are. What's your point?

>
> Mixing data and program code, ie.. variable names as data, is not a
> good idea.

Down with eval! Exile exec! A pox on both their houses!

(i.e. I respectfully disagree that mixing data with program code is a bad idea)

Peace
Bill Mill
bill.mill at gmail.com

Cameron Laird

unread,
Mar 29, 2005, 1:08:04 PM3/29/05
to
In article <mailman.1017.1112113...@python.org>,
Bill Mill <bill...@gmail.com> wrote:
.
.
.

>(i.e. I respectfully disagree that mixing data with program code is a bad idea)
.
.
.
Most applications (as opposed to "system") developers should be doing
it rarely. VERY often when they seem inclined to do so, it's just a
symptom of a confused design.

In no way do I mean to restrict knowledgeable metaclass authors, LISPers,
debugger inventors, or other legitimate exceptions to my claim.

Bill Mill

unread,
Mar 29, 2005, 1:40:37 PM3/29/05
to Cameron Laird, pytho...@python.org
On Tue, 29 Mar 2005 18:08:04 GMT, Cameron Laird <cla...@lairds.us> wrote:
> In article <mailman.1017.1112113...@python.org>,
> Bill Mill <bill...@gmail.com> wrote:
> .
> .
> .
> >(i.e. I respectfully disagree that mixing data with program code is a bad idea)
> .
> .
> .
> Most applications (as opposed to "system") developers should be doing
> it rarely. VERY often when they seem inclined to do so, it's just a
> symptom of a confused design.

On that point I can agree. I just wanted to say that there are
valuable uses for mixing code and data. As soon as I sent my email
out, I realized that I meant to say that mixing data with program code
is *not always* a bad idea.

Particularly, yelling at this guy for wanting to figure out a
variable's name is, I think, overzealous. If he just wants to use it
for debugging, then I don't know why he needs to be shouted down.

>
> In no way do I mean to restrict knowledgeable metaclass authors, LISPers,
> debugger inventors, or other legitimate exceptions to my claim.

I'm confused. Are you ron_adam, cameron laird, or both?

Either way, your point is well taken, and I should have been clearer
in my overly glib email.

Ron_Adam

unread,
Mar 29, 2005, 2:28:48 PM3/29/05
to
On Tue, 29 Mar 2005 11:23:45 -0500, Bill Mill <bill...@gmail.com>
wrote:

>On Tue, 29 Mar 2005 14:34:39 GMT, Ron_Adam <rad...@tampabay.rr.com> wrote:
>> On 28 Mar 2005 23:01:34 -0800, "Dan Bishop" <dan...@yahoo.com> wrote:
>>
>> >>>> def print_vars(vars_dict=None):
>> >... if vars_dict is None:
>> >... vars_dict = globals()
>> >... for var, value in vars_dict.items():
>> >... print '%s = %r' % (var, value)
>> >...
>> >>>> myPlace = 'right here'
>> >>>> myTime = 'right now'
>> >>>> print_vars()
>> >print_vars = <function print_vars at 0x401e0d84>
>> >__builtins__ = <module '__builtin__' (built-in)>
>> >myTime = 'right now'
>> >myPlace = 'right here'
>> >__name__ = '__main__'
>> >__doc__ = None
>>
>> Fred = 5
>> John = 8
>> Winner = John
>>
>> Both John and Winner are pointing to the literal '8'.
>
>ummm, yes, of course they are. What's your point?

Hi Bill,

My point is if you look up the name and print it, you may get.

Instead of:

Fred has 5 points
John has 8 points

You could get:

Fred has 5 points
Winner has 8 points

Or something else depending on how many references you made to the
value 8.



>> Mixing data and program code, ie.. variable names as data, is not a
>> good idea.
>
>Down with eval! Exile exec! A pox on both their houses!
>
>(i.e. I respectfully disagree that mixing data with program code is a bad idea)

(I respectfully acknowledged your opinion.)

To be fair, it's not always bad. But in most cases it is better not
too.

I wasn't referring to using exec or eval, but to directly using data
values in the program code.

Here's an example of mixing data and code. If I write a program that
checks a list for specific names and prints corresponding value for
each.

I would not do this: ( Lots of stuff wrong with this example! )

playerlist = ['John','Bob','Fred']
John = 6
Bob = 8
Fred = 0

for name in playerlist:
if item == 'John':
print 'John', John
if item == 'Bob':
print 'Bob', Bob

This is only good for one set of data, and each time my data changes,
I would need to rewrite the program code also. This has data as
program code in both the variables and in the comparisons.

Not mixing data and code:

playerlist = {'John':6, 'Bob':8, 'Fred',0}
players = ['John', 'Bob']

for name in players:
print name, playerlist[name]

This does the same thing as above, but data and program code are not
mixed. It's much easier to maintain and reuse.

Ron

Bill Mill

unread,
Mar 29, 2005, 2:58:45 PM3/29/05
to Ron_Adam, pytho...@python.org
<snip>

> >>
> >> Fred = 5
> >> John = 8
> >> Winner = John
> >>
> >> Both John and Winner are pointing to the literal '8'.
> >
> >ummm, yes, of course they are. What's your point?
>
> Hi Bill,
>
> My point is if you look up the name and print it, you may get.
>
> Instead of:
>
> Fred has 5 points
> John has 8 points
>
> You could get:
>
> Fred has 5 points
> Winner has 8 points
>
> Or something else depending on how many references you made to the
> value 8.

Yes, this is true, assuming that he looks for keys with the value 8 in
locals(). It's not necessarily true if there's a way to ask python
what the name of John is, which is what the OP was asking. I just
wanted you to explicitly say what you were implying so that we could
discuss it.

>
> >> Mixing data and program code, ie.. variable names as data, is not a
> >> good idea.
> >
> >Down with eval! Exile exec! A pox on both their houses!
> >
> >(i.e. I respectfully disagree that mixing data with program code is a bad idea)
>
> (I respectfully acknowledged your opinion.)
>
> To be fair, it's not always bad. But in most cases it is better not
> too.
>

Yup, I meant to say that I disagree that mixing data with program code
is *always* a bad idea. I had a "d'oh!" moment when I hit send.

<code arguing against maintining an ad-hoc locals()>

Naturally, I wasn't suggesting that anyone (shudder) do things like
your examples of poor code. I had a much smaller point, about which I
was not clear: Sometimes, it is handy to mix code and data. There
*are* legitimate uses of reflection, eval, and exec.

I was too glib in my response to you. I intended no disrespect, only silliness.

Ron_Adam

unread,
Mar 29, 2005, 3:42:36 PM3/29/05
to
On Tue, 29 Mar 2005 14:58:45 -0500, Bill Mill <bill...@gmail.com>
wrote:

<folded>

>>
>> Or something else depending on how many references you made to the
>> value 8.
>
>Yes, this is true, assuming that he looks for keys with the value 8 in
>locals(). It's not necessarily true if there's a way to ask python
>what the name of John is, which is what the OP was asking. I just
>wanted you to explicitly say what you were implying so that we could
>discuss it.

ok, :)

I should have explained my position better the first time. I was a bit
too brief.

Unfortunately, while class's and functions have a __name__ attribute,
simple data types do not.

I've been playing around with a way to explore name spaces, but once
you drop into class's, and functions, the references can lead you into
an endless loops.

>
>Yup, I meant to say that I disagree that mixing data with program code
>is *always* a bad idea. I had a "d'oh!" moment when I hit send.
>

I do that more often than I like. Maybe I should have said 'is often'
not a good idea.

>
>Naturally, I wasn't suggesting that anyone (shudder) do things like
>your examples of poor code. I had a much smaller point, about which I
>was not clear: Sometimes, it is handy to mix code and data. There
>*are* legitimate uses of reflection, eval, and exec.

I did't think you would suggest that, but I thought it was a good
chance to clarify what I meant the first time. If you missed my point,
then so did others. An obvious example is sometimes the best way to
demonstrate a basic concept.

There are good uses for eval and exec. Ultimately it's up to the
programmer to decide the best use of the tools. I just like to keep
my tools(code), and my parts(data) in separate bins. ;)


Ron

Duncan Booth

unread,
Mar 30, 2005, 3:43:17 AM3/30/05
to
Ron_Adam wrote:

> I've been playing around with a way to explore name spaces, but once
> you drop into class's, and functions, the references can lead you into
> an endless loops.
>

Here is a rough attempt at printing the names of a variable. It will pick
up several names where appropriate, but deliberately doesn't attempt to
get all possible names (as you say, that could result in endless loops).
In particular, for the Fred=5/John=8/Winner=8 example it will only find
one of John or Winner since it only picks at most one match from each dict
or list. It doesn't yet manage to correctly lookup attributes (e.g. slots)
when they aren't stored in a __dict__, nor does the output distinguish
between dictionary keys and values (so encodings.cp437.encoding_map[8]
below actually refers to the key not the value).

If you want to track down a memory leak with this code save a weak
reference to the variable you expect to be saved and then you may be able
to work out why it hasn't been freed later on. I originally wrote a version
of this code because I was having problems with xml.dom.ext.reader.HtmlLib
(its parser holds onto the DOM from a C extension object which doesn't
support garbage collection). In that situation you get variable 'names'
beginning with '...' since there is no named variable to start from, but
the attributes make it easier to track down which objects are involved and
where the circular loops are.

Python 2.4 (#60, Nov 30 2004, 11:49:19) [MSC v.1310 32 bit (Intel)] on
win32 Type "help", "copyright", "credits" or "license" for more
information.

>>> Fred = 5
>>> John = 8
>>> Winner = John

>>> import varname
>>> for s in varname.object_info(Winner, False):
... print s
...
sre_parse.ESCAPES['\\b'][1]
tokenize.tok_name[8]
token.tok_name[8]
sre_parse.OPCODES['call']
sre_parse.FLAGS['m']
sre_parse.CHCODES['category_loc_word']
sre_parse.ATCODES['at_loc_boundary']
sre_constants.OPCODES['call']
sre_constants.CHCODES['category_loc_word']
sre_constants.ATCODES['at_loc_boundary']
sre_compile.OPCODES['call']
sre_compile.CHCODES['category_loc_word']
sre_compile.ATCODES['at_loc_boundary']
encodings.cp437.encoding_map[8]
encodings.cp437.decoding_map[8]
encodings.cp1252.encoding_map[8]
encodings.cp1252.decoding_map[8]
string.expandtabs[0]
tokenize.RPAR
token.RPAR
stat.ST_MTIME
sre_parse.SRE_FLAG_MULTILINE
sre_constants.SRE_FLAG_MULTILINE
sre_compile.SRE_FLAG_MULTILINE
sre.M
signal.SIGFPE
re.M
os.O_APPEND
nt.O_APPEND
inspect.CO_VARKEYWORDS
imp.PY_CODERESOURCE
gc.DEBUG_INSTANCES
__main__.Winner
>>>
>>> class C:
... def foo(self):
... x = 'Hello '+'world'
... for s in varname.object_info(x):
... print s
...
>>> C().foo()
__main__.C.foo()x
>>>

---------- varname.py ------------
import gc, inspect, types, operator

def locate_keyorvalue(obj, container):
if isinstance(container, dict):
for k, v in container.iteritems():
if v is obj:
return 'value', k
if k is obj:
return 'key', k
else:
for i, x in enumerate(container):
if x is obj:
return 'index', i

return '???', ''

def object_info(obj, anonymous=True):
gc.collect()

tree = {}
ignored = {}
def ignore(obj):
ignored[id(obj)] = 1
def unignore(obj):
del ignored[id(obj)]

def safeshow(o):
if isinstance(o, (list, dict)):
return type(o)
return o

def buildTree(obj):
'''Build a tree of referrers to obj such that
tree[id(obj)] -> list of referrers
'''
ignore(inspect.currentframe())

objects = [obj]
while objects:
current = objects.pop()
#print "current", type(current), hex(id(current))

if isinstance(current, (types.ModuleType, )):
refs = [] # Don't extend references to modules
else:
refs = [ o for o in gc.get_referrers(current) if not id(o) in ignored ]
ignore(refs)

tree[id(current)] = refs

modules = [ r for r in refs if isinstance(r, (types.ModuleType,)) ]
if modules:
objects.extend(modules)
tree[id(current)] = modules
else:
# Not yet found a path from a module
for r in refs:
if not id(r) in tree:
objects.append(r)

ignore(inspect.currentframe())
ignore(tree)

buildTree(obj)

def findPath(obj, ignore):
'''Find a path from 'obj' back as far as it will go in the tree'''
ignore[id(obj)] = 1

referrers = tree[id(obj)]
if referrers:
for t in referrers:
if id(t) in ignore:
yield ['...', t, obj]
else:
for path in findPath(t, ignore):
yield path + [obj]
else:
yield [obj]

del ignore[id(obj)]


ignores = {}
SCORES = {
types.ModuleType: 100,
type: 70,
types.ClassType: 60,
types.FrameType: 20,
list: 10, dict:10
}
results = []
for p in findPath(obj, ignores):
score = []
result = []
while p:
this = p.pop(0)
#print type(this)
if hasattr(this, '__dict__') and p[0]==this.__dict__:
next = p.pop(0)
name = locate_keyorvalue(p[0], next)
if not result:
result.append(this.__name__)
result.append('.')
result.append(name[1])

elif isinstance(this, types.FrameType):
style, name = locate_keyorvalue(p[0], this.f_locals)
code = this.f_code
result.append("%s()" % object_info(this.f_code).next())
result.append(name)

elif isinstance(this, types.GeneratorType):
break
else:
if isinstance(this, (tuple, list, dict)) and len(p):
style, name = locate_keyorvalue(p[0], this)
if not result:
if not anonymous:
break
result.append('<anonymous %s@%s>' % (type(this).__name__,id(this)))
result.append('[%r]' % name)
else:
if not result:
if not anonymous:
break
result.append('<%s>' % (this,))
#print this
break
score.append(SCORES.get(type(this), 0))

if result:
results.append((score, str.join('', result)))
#yield str.join('', result), score
result = []

for r in sorted(results, reverse=True):
yield r[1]
return

if __name__=='__main__':
def test():
v1 = 'abc'+'def'
print "Info for",repr(v1)
for s in object_info(v1):
print s

class Fred(object):
__classvar = 'xyzzy1'
def foo(self, v):
print "Info for", repr(v)
for s in object_info(v):
print s
print

myvar = Fred()
myvar.abc = 'xyzzy1'
pqr = (0, myvar.abc, 1)

aDict = {}
aDict[myvar.abc] = 'xyzzy1'

def test1(x):
print "Info for", repr(x)
for s in object_info(x, False):
print s
print
test1('xyzzy1')

myvar.foo('pqr'+'stu')
test()

#test1(None)
----------------------------------

stewart....@gmail.com

unread,
Mar 31, 2005, 12:56:06 AM3/31/05
to
my god, I've created a monster!

Maybe I should restate my original problem. Actually, the word
'problem' is too strong. I had a little curiosity about whether I could
write a couple of lines of code more succinctly, or more pythonically.
I didn't realize that this would trigger a discussion about mixing
data and objects - though I can see the danger if you get into some
situations. Hopefully mine is not one of those.

Restating: I'm doing some debugging of some code. I want to print out
the value of two variables whose names are known. Let's call them
myTime and myPlace.

#debug:
if self.debug:
print "myTime = %s, myPlace = %s" % (myTime, myPlace)

Notice that I had to type the variable's name once as an object, and
once as the string representation of that object, i.e. the object's
name.
I wondered whether it might not be possible to do something like this:
if self.debug:
print "%s = %s" % ( name(myTime), myTime )
where 'name' is the method or trick I'm after.

Creating a dictionary is already more work than it's worth, not to
mention some of the more involved solutions. I'm left to conclude
that it's not possible to do what I wanted with Python. If that's the
case, so be it and I'll move on to explore other curiosities.

But surely if you create an integer object and assign it a value, e.g.
a = 3,
why shouldn't Python be able to tell you something like the following:
name(a) >>> 'a'
?

thanks
S

Aaron Bingham

unread,
Mar 31, 2005, 1:49:39 AM3/31/05
to stewart....@gmail.com, pytho...@python.org
"stewart....@gmail.com" <stewart....@gmail.com> writes:

> Restating: I'm doing some debugging of some code. I want to print out
> the value of two variables whose names are known. Let's call them
> myTime and myPlace.
>
> #debug:
> if self.debug:
> print "myTime = %s, myPlace = %s" % (myTime, myPlace)
>
> Notice that I had to type the variable's name once as an object, and
> once as the string representation of that object, i.e. the object's
> name.
> I wondered whether it might not be possible to do something like this:
> if self.debug:
> print "%s = %s" % ( name(myTime), myTime )
> where 'name' is the method or trick I'm after.

I must admit this is a bit of a sore point with me: this could be
solved so easily with a nice little macro <ducks>. For the case where
you only want to print the name and value of a variable (as opposed to
that of an expression), you may find this little function helpful:

def print_variable(name, scope):
print "%s = %r" % (name, scope[name])

You can call it like this:

print_variable('myTime', locals())

Not perfect, because you have to repeat locals() every time, but it
does save the repetition of the variable name.

Printing expressions can also be accomplished in a similar but more
dangerous[*] fashion:

def print_expression(expression, local_scope, global_scope=None):
if global_scope is None:
global_scope = globals()
print "%s = %r" % (expression,
eval(expression, local_scope, global_scope))

Example:

print_expression('i+1', locals())

[*] The use of eval here would make allowing user-entered expressions
here very dangerous, but as long as as it is used as a debugging
aid, with the expression as a literal string in the program, there
should be no security issue. I would never use either of these
functions except as debugging aids anyway.

Regards,

--
--------------------------------------------------------------------
Aaron Bingham
Software Engineer
Cenix BioScience GmbH
--------------------------------------------------------------------

Stewart Midwinter

unread,
Mar 31, 2005, 2:57:14 AM3/31/05
to Aaron Bingham, pytho...@python.org
thanks Aaron, I'll pick what's behind door no. 1 !
That is, I liked your first solution. Having said that, I would only
have to place either solution once in my code, then I could call it
again and again. So either one would be just as 'light' in actual
usage.

Taking this idea a little further, I'd like to build a 'variable
inspector' for my GUI app, so that I don't have to resort to debug
statements. Instead, I could pop open a window that lists every
variable that has an expected None, string, int or float value, and
select any one in order to see its value at that time. I believe your
method would be useful in that situation as well, no?

cheers,
--
Stewart Midwinter
ste...@midwinter.ca
stewart....@gmail.com
Skype: midtoad

Duncan Booth

unread,
Mar 31, 2005, 3:13:30 AM3/31/05
to
stewart....@gmail.com wrote:

> But surely if you create an integer object and assign it a value, e.g.
> a = 3,
> why shouldn't Python be able to tell you something like the following:
> name(a) >>> 'a'
> ?

But why should it return 'a' and not one of these?

tokenize.tok_name[3]
token.tok_name[3]
sre_parse.OPCODES['any_all']
sre_parse.CHCODES['category_not_space']
sre_parse.ATCODES['at_boundary']
sre_constants.OPCODES['any_all']
sre_constants.CHCODES['category_not_space']
sre_constants.ATCODES['at_boundary']
sre_compile.OPCODES['any_all']
sre_compile.CHCODES['category_not_space']
sre_compile.ATCODES['at_boundary']
opcode.opmap['ROT_THREE']
encodings.cp437.encoding_map[3]
encodings.cp437.decoding_map[3]
encodings.cp1252.encoding_map[3]
encodings.cp1252.decoding_map[3]
dis.opmap['ROT_THREE']
tokenize.STRING
token.STRING
stat.ST_NLINK
os.P_NOWAITO
nt.P_NOWAITO
locale.LC_MONETARY
imp.C_EXTENSION
_locale.LC_MONETARY

The important thing is that not only do these variables all have the value
3, they all have the *same* value 3. That monstrous code I posted behaves a
little differently if you give it a number such as 101:

>>> x = 101
>>> for s in varname.object_info(101):
... print s
...
<anonymous tuple@10292480>[0]

The variable 'x' is ignored because it contains a different 101, the only
thing in the system using the specific 101 that was passed to object_info
is the tuple used to contain the constants for the executing code. Asking
for object_info(x) will indeed return only one string '__main__.x'.

The key here is to understand the difference between languages like C where
a variable is a container used to store a value and Python where variables
are simply the binding of names to objects.

Bengt Richter

unread,
Mar 31, 2005, 3:33:25 AM3/31/05
to
On 30 Mar 2005 21:56:06 -0800, "stewart....@gmail.com" <stewart....@gmail.com> wrote:

>my god, I've created a monster!
>
>Maybe I should restate my original problem. Actually, the word
>'problem' is too strong. I had a little curiosity about whether I could
>write a couple of lines of code more succinctly, or more pythonically.
> I didn't realize that this would trigger a discussion about mixing
>data and objects - though I can see the danger if you get into some
>situations. Hopefully mine is not one of those.
>
>Restating: I'm doing some debugging of some code. I want to print out
>the value of two variables whose names are known. Let's call them
>myTime and myPlace.
>
>#debug:
>if self.debug:
> print "myTime = %s, myPlace = %s" % (myTime, myPlace)
>
>Notice that I had to type the variable's name once as an object, and
>once as the string representation of that object, i.e. the object's
>name.
>I wondered whether it might not be possible to do something like this:
>if self.debug:
> print "%s = %s" % ( name(myTime), myTime )
>where 'name' is the method or trick I'm after.

Why isn't name(myTime) just 'myTime' ?
Which of the possible aliases would you like, if that's what you're looking for?

>

Anyway, if you just want a way of generating the string 'x = <the value of x>' without
typing 'x' twice, you can use a custom mapping class and a __getitem__ method to
do the work. E.g.,

>>> class ShowEq(dict):
... def __getitem__(self, name):
... return '%s = %r'%(name, self.get(name, '<UNDEF!!>'))
...

Some variables
>>> a,b = 'eigh', 'bee'

print them, using an instance of the mapping initialized with vars() which is the local namespace

>>> print '%(a)s, %(b)s, %(ShowEq)s' % ShowEq(vars())
a = 'eigh', b = 'bee', ShowEq = <class '__main__.ShowEq'>


Which does something like

print "%(myTime)s = %s" % ( name(myTime), myTime )

I've forgotten who first did this, but I think it was before you could subclass dict ;-)



>Creating a dictionary is already more work than it's worth, not to
>mention some of the more involved solutions. I'm left to conclude
>that it's not possible to do what I wanted with Python. If that's the
>case, so be it and I'll move on to explore other curiosities.

Sometimes it's hard to get across exactly what it is you want, so don't give up until
you're sure you're being understood ;-)


>
>But surely if you create an integer object and assign it a value, e.g.

The way you use those words makes me wonder: "assign _it_"?? Which 'it'?
The integer object in this is created from the right hand side of the '='.
Assignment is attaching a name tag (with the name from the left on it) to the
object with sufficient sewing thread to reach a bulletin board where you tack up the tag.
A bare name is tacked on the local bulletin board (name space). The integer object is nameless
in itself. And the name is not the object. The name just leads to the object -- until the lead
is cut and tied to something else (rebound), or the tag is taken off the bulletin board (deleted),
at which time the object may have other names from the same or other bulletin boards (or container
binding sites) attached to it. If there's nothing connected, the object goes in the garbage.

>a = 3,
>why shouldn't Python be able to tell you something like the following:
>name(a) >>> 'a'

Because there is in general no unique 'a' associated with the object that has already been looked
up and is being passed by reference to name(). What should you get for name(7)? There might be no name.

To get an idea, try to write a C routine to do it, being passed a pointer to a memory location
allocated with malloc. What name should it return? How should it find a name?

If you are willing to prefix your names with the name of a special namespace whenever you refer to them,
so it would be name(ns.a) >>> 'a', that could be be done. You can do about anything through descriptor
magic and overriding __get/setattr/ibute__ and spell things in a way that totally abuses
the design intents of Python ;-)

Regards,
Bengt Richter

Bill Mill

unread,
Mar 31, 2005, 3:33:10 AM3/31/05
to duncan...@suttoncourtenay.org.uk, pytho...@python.org
On 31 Mar 2005 08:13:30 GMT, Duncan Booth <duncan...@invalid.invalid> wrote:
> stewart....@gmail.com wrote:
>
> > But surely if you create an integer object and assign it a value, e.g.
> > a = 3,
> > why shouldn't Python be able to tell you something like the following:
> > name(a) >>> 'a'
> > ?
>
> But why should it return 'a' and not one of these?

Because the python interpreter certainly knows the name of all the
variables used in a python program. So, a name() function as discussed
here should return the name of the exact variable passed in as input,
not any variable which refers to the value 3 (which is of course
constant). We're imagining a new function, not discussing yours.


.
>
> The key here is to understand the difference between languages like C where
> a variable is a container used to store a value and Python where variables
> are simply the binding of names to objects.

I don't see any technical barrier to implementing a name() function,
except that either the current CPython doesn't allow this particular
reflection from python, or it's difficult to do. Just because a
variable is simply a name binding doesn't mean Python couldn't return
the name of the binding.

I'm not definitely saying that I *want* an easy name() function -
there's a lot of potential for abuse - but I would at least like to
see it accomplished before I decide whether I like it or not.

Bill Mill

unread,
Mar 31, 2005, 3:37:19 AM3/31/05
to duncan...@suttoncourtenay.org.uk, pytho...@python.org
On Thu, 31 Mar 2005 03:33:10 -0500, Bill Mill <bill...@gmail.com> wrote:
> On 31 Mar 2005 08:13:30 GMT, Duncan Booth <duncan...@invalid.invalid> wrote:
> > stewart....@gmail.com wrote:
> >
> > > But surely if you create an integer object and assign it a value, e.g.
> > > a = 3,
> > > why shouldn't Python be able to tell you something like the following:
> > > name(a) >>> 'a'
> > > ?
> >
> > But why should it return 'a' and not one of these?
>
> Because the python interpreter certainly knows the name of all the
> variables used in a python program. So, a name() function as discussed
> here should return the name of the exact variable passed in as input,
> not any variable which refers to the value 3 (which is of course
> constant). We're imagining a new function, not discussing yours.

Reason #312 not to post at 3:30 AM:

Ok, the variable name is evaluated before being passed to the
function. Thus, it would require some pretty heavy interpreter
trickery to implement. I take back what I said.

Humbly,

Aaron Bingham

unread,
Mar 31, 2005, 4:04:55 AM3/31/05
to Stewart Midwinter, pytho...@python.org
Stewart Midwinter <stewart....@gmail.com> writes:

[snip]

> Taking this idea a little further, I'd like to build a 'variable
> inspector' for my GUI app, so that I don't have to resort to debug
> statements. Instead, I could pop open a window that lists every
> variable that has an expected None, string, int or float value, and
> select any one in order to see its value at that time. I believe your
> method would be useful in that situation as well, no?

For that, I would suggest taking a look at Komodo
(http://www.activestate.com/Products/Komodo/) and its remote debugging
functionality, instead of building your own tool. There may be other
IDEs that provide equivalent functionality, but I am not familiar with
them.

Ron_Adam

unread,
Mar 31, 2005, 1:10:22 PM3/31/05
to
On 30 Mar 2005 08:43:17 GMT, Duncan Booth
<duncan...@invalid.invalid> wrote:

>Here is a rough attempt at printing the names of a variable. It will pick
>up several names where appropriate, but deliberately doesn't attempt to
>get all possible names (as you say, that could result in endless loops).
>In particular, for the Fred=5/John=8/Winner=8 example it will only find
>one of John or Winner since it only picks at most one match from each dict
>or list. It doesn't yet manage to correctly lookup attributes (e.g. slots)
>when they aren't stored in a __dict__, nor does the output distinguish
>between dictionary keys and values (so encodings.cp437.encoding_map[8]
>below actually refers to the key not the value).


Here's what I've been working on. It still has some glitches in it
but I think it has potential as a instructional/diagnostict tool

I'm going to repost this with the source as it's own topic, maybe it
can be developed further. :)

Cheers,
Ron

IDLE 1.1.1c1 ==== No Subprocess ====
>>> from pnames import pnames
>>> pnames()
[globals]
__builtins__ --> <module>
__doc__ --> <docstring>
__file__ --> C:\Python24\Lib\idlelib\idle.pyw
__name__ --> __main__
idlelib --> <module>
pnames --> <function>
Paused
>>> John = 8
>>> Fred = 6
>>> Winner = John
>>> players = [John, Fred]
>>> pnames()
[globals]
__builtins__ --> <module>
__doc__ --> <docstring>
__file__ --> C:\Python24\Lib\idlelib\idle.pyw
__name__ --> __main__
Fred --> 6
idlelib --> <module>
John --> 8
players --> [8, 6]
pnames --> <function>
Winner --> 8
Paused

Both winner and John point to the litteral '8', but since the number
'8' can never be changed, it doesn't matter, but you can look up the
number '8' and find both John and Winner, but changing one, doesn't
change the other.


>>> John = 9
>>> pnames()
[globals]
__builtins__ --> <module>
__doc__ --> <docstring>
__file__ --> C:\Python24\Lib\idlelib\idle.pyw
__name__ --> __main__
Fred --> 6
idlelib --> <module>
John --> 9
players --> [8, 6]
pnames --> <function>
Winner --> 8
Paused

Winner didn't change it's value.


>>> scores = players
>>> pnames()
[globals]
__builtins__ --> <module>
__doc__ --> <docstring>
__file__ --> C:\Python24\Lib\idlelib\idle.pyw
__name__ --> __main__
Fred --> 6
idlelib --> <module>
John --> 9
players --> [8, 6] <-- scores
pnames --> <function>
scores --> [8, 6] <-- players
Winner --> 8
Paused
>>>

Here, players and scores are both mutable, changeing them will change
the other and so it shows that the list [8,6] has more than one name.


Cheers,
Ron

stewart....@gmail.com

unread,
Mar 31, 2005, 11:54:42 PM3/31/05
to
Bengt wrote:
"The way you use those words makes me wonder: "assign _it_"?? Which
'it'? "

- it's probably evident to any close observer that my understanding of
objects is superficial, no doubt a reflection of the fact that I
started programming on punch cards a very long time ago. I use objects
every day, but I clearly need to do some further study in order to
develop my knowledge.

Thanks for your explanations.!

Bengt Richter

unread,
Apr 1, 2005, 2:03:55 AM4/1/05
to

You're welcome. But I started programming with flexowriter punched
paper tape before I got to punch cards, so either the prognosis is hopeful or
maybe you should take what I write with a grain or two of salt. Probably both ;-)

Regards,
Bengt Richter

John J. Lee

unread,
Apr 1, 2005, 2:56:28 PM4/1/05
to
"stewart....@gmail.com" <stewart....@gmail.com> writes:
[...]

> Restating: I'm doing some debugging of some code. I want to print out
> the value of two variables whose names are known. Let's call them
> myTime and myPlace.
[...]

Why not simply get your editor to insert the variable name twice? I
have that bound to C-c d in my .emacs.


John

0 new messages