Say I have a variable named choice
it is equal to 2. How would I access the name of the variable? Something equivalent to
In [53]: namestr(choice)
Out[53]: 'choice'
for use in making a dictionary. There's a good way to do this and I'm just missing it.
EDIT:
The reason to do this is thus. I am running some data analysis stuff where I call the program with multiple parameters that I would like to tweak, or not tweak, at runtime. I read in the parameters I used in the last run from a .config file formated as
filename
no_sig_resonance.dat
mass_peak
700
choice
1,2,3
When prompted for values, the previously used is displayed and an empty string input will use the previously used value.
My question comes about because when it comes to writing the dictionary that these values have been scanned into. If a parameter is needed I run get_param
which accesses the file and finds the parameter.
I think I will avoid the problem all together by reading the .config
file once and producing a dictionary from that. I avoided that originally for... reasons I no longer remember. Perfect situation to update my code!
This question is related to
python
dictionary
variables
introspection
If you insist, here is some horrible inspect-based solution.
import inspect, re
def varname(p):
for line in inspect.getframeinfo(inspect.currentframe().f_back)[3]:
m = re.search(r'\bvarname\s*\(\s*([A-Za-z_][A-Za-z0-9_]*)\s*\)', line)
if m:
return m.group(1)
if __name__ == '__main__':
spam = 42
print varname(spam)
I hope it will inspire you to reevaluate the problem you have and look for another approach.
You can't, as there are no variables in Python but only names.
For example:
> a = [1,2,3]
> b = a
> a is b
True
Which of those two is now the correct variable? There's no difference between a
and b
.
There's been a similar question before.
Will something like this work for you?
>>> def namestr(**kwargs):
... for k,v in kwargs.items():
... print "%s = %s" % (k, repr(v))
...
>>> namestr(a=1, b=2)
a = 1
b = 2
And in your example:
>>> choice = {'key': 24; 'data': None}
>>> namestr(choice=choice)
choice = {'data': None, 'key': 24}
>>> printvars(**globals())
__builtins__ = <module '__builtin__' (built-in)>
__name__ = '__main__'
__doc__ = None
namestr = <function namestr at 0xb7d8ec34>
choice = {'data': None, 'key': 24}
Rather than ask for details to a specific solution, I recommend describing the problem you face; I think you'll get better answers. I say this since there's almost certainly a better way to do whatever it is you're trying to do. Accessing variable names in this way is not commonly needed to solve problems in any language.
That said, all of your variable names are already in dictionaries which are accessible through the built-in functions locals and globals. Use the correct one for the scope you are inspecting.
One of the few common idioms for inspecting these dictionaries is for easy string interpolation:
>>> first = 'John'
>>> last = 'Doe'
>>> print '%(first)s %(last)s' % globals()
John Doe
This sort of thing tends to be a bit more readable than the alternatives even though it requires inspecting variables by name.
With eager evaluation, variables essentially turn into their values any time you look at them (to paraphrase). That said, Python does have built-in namespaces. For example, locals() will return a dictionary mapping a function's variables' names to their values, and globals() does the same for a module. Thus:
for name, value in globals().items():
if value is unknown_variable:
... do something with name
Note that you don't need to import anything to be able to access locals() and globals().
Also, if there are multiple aliases for a value, iterating through a namespace only finds the first one.
For the revised question of how to read in configuration parameters, I'd strongly recommend saving yourself some time and effort and use ConfigParser or (my preferred tool) ConfigObj.
They can do everything you need, they're easy to use, and someone else has already worried about how to get them to work properly!
def namestr(obj, namespace):
return [name for name in namespace if namespace[name] is obj]
Example:
>>> a = 'some var'
>>> namestr(a, globals())
['a']
As @rbright already pointed out whatever you do there are probably better ways to do it.
If you are trying to do this, it means you are doing something wrong. Consider using a dict
instead.
def show_val(vals, name):
print "Name:", name, "val:", vals[name]
vals = {'a': 1, 'b': 2}
show_val(vals, 'b')
Output:
Name: b val: 2
Source: Stackoverflow.com