Simpler way to create dictionary of separate variables?
Asked Answered
P

27

225

I would like to be able to get the name of a variable as a string but I don't know if Python has that much introspection capabilities. Something like:

>>> print(my_var.__name__)
'my_var'

I want to do that because I have a bunch of variables I'd like to turn into a dictionary like :

bar = True
foo = False
>>> my_dict = dict(bar=bar, foo=foo)
>>> print my_dict 
{'foo': False, 'bar': True}

But I'd like something more automatic than that.

Python have locals() and vars(), so I guess there is a way.

Pteryla answered 31/3, 2010 at 13:39 Comment(4)
Since people seem to be confused about what's asked for I'll restate it here because it's an interesting question. Given an array [foo, bar, baz] you want a dictionary like {'foo': foo, 'bar': bar, 'baz': baz} and you don't know what variables are in the array. so the questioner is asking how you get name of a variable as a string in python. Now hopefully people can navigate through the awful responses to find the few places where you learn why this isn't really a good idea in python.Floccus
Possible duplicate: #545419Storm
One use for technique would be to streamline string formatting calls: '{var} {foo} {bar}'.format(**named(var, foo, bar)), where "named" is the function that returns the dict('var': var) as described.Retinoscopy
I think this is actually a bad question because names are mapped to objects, you can have multiple names pointing to the same object, and I have never seen any need to accomplish the goal of inverting that mapping. So the fact that the wrong answer is accepted here is meaningless - if a google search brought you here, you are clearly asking the wrong question.Kerbstone
H
47

Are you trying to do this?

dict( (name,eval(name)) for name in ['some','list','of','vars'] )

Example

>>> some= 1
>>> list= 2
>>> of= 3
>>> vars= 4
>>> dict( (name,eval(name)) for name in ['some','list','of','vars'] )
{'list': 2, 'some': 1, 'vars': 4, 'of': 3}
Hooten answered 31/3, 2010 at 13:59 Comment(10)
Nice one S.Lott. Never far away from a Python question, ain't you? This is the closest we can get I guess, given that we apparently can't get access to the many names that point to a variable value. Not totally automatic, but close enough.Pteryla
@e-satis: What could be more automatic than this? What are you talking about? All variables are already in locals.Hooten
rlotun is closer to the initial "spirit" of it since it allows to discover the name. I will could use both your anwser. Or maybe just use my damn hand to type. Some things are just not made to be that automatized...Pteryla
@e-satis: For @rlotun's to work, you have to provide the list of variables. If you have the list of variables, what's the point of "discovering" their names?Hooten
Why eval instead of explicitly using locals and globals?Karlin
@Roger Pate: Because I couldn't figure out what the point of the whole exercise was.Hooten
This answer does not answer the question asked. If you have the list of variables, what's the point of "discovering" their names? To avoid duplication so that instead of print('x: ' + x) one could write magic_print(x) and have the same output without writing variable's name twice.Semidome
@PiotrDobrogost: have you found a way to do it? Great point by the way! My attempts to build your magic_print led me to the question in the first place.Stabler
@Hooten The "point" in my case is quite simple: I'd rather read foo in a log than '<function foo at 0x7f08ba9ad400>' I have a queue that holds method calls + arguments for delayed execution, and I'd like to log the name of the method about to be called.Solarize
@PiotrDobrogost That follows from this answer: def magic_print(x): print("%s: %s" % (x, eval(x)) then magic_print('x'). If you don't know the variable name, see #545419Serrulation
C
131

As unwind said, this isn't really something you do in Python - variables are actually name mappings to objects.

However, here's one way to try and do it:

 >>> a = 1
 >>> for k, v in list(locals().iteritems()):
         if v is a:
             a_as_str = k
 >>> a_as_str
 a
 >>> type(a_as_str)
 'str'
Conure answered 31/3, 2010 at 13:54 Comment(7)
This idea has merit, but note that if two variable names reference the same value (e.g. True), then an unintended variable name might be returned.Humpbacked
Why id(v) == id(a) instead of v is a? This will fail for objects bound to multiple variables, such as ints, strings, and any similarly implemented user-defined types.Karlin
Yes, v is a would be a better choice. And yes, certainly dangerous given all the potential pitfalls that could arise! ;-)Conure
@e-satis I'm surprised you haven't marked this answer as the answer as I agree with your comment saying rlotun is closer to the initial "spirit" of it since it allows to discover the name. Additionally S.Lott's answer does not aswer your question at all...Semidome
"overkill and dangerous"... and using eval isn't ?Hurtado
"Why id(v) == id(a) instead of v is a? This will fail for objects bound to multiple variables, such as ints, strings, and any similarly implemented user-defined types" can someone explain with an example, I can't see the difference for this implementation.Grange
If you'd like to use this in a function: def var_name(asdkjalskdjklasd): for (k,v) in globals().items(): if k is not 'asdkjalskdjklasd' and v is asdkjalskdjklasd: return kLyndes
D
63

I've wanted to do this quite a lot. This hack is very similar to rlotun's suggestion, but it's a one-liner, which is important to me:

blah = 1
blah_name = [ k for k,v in locals().iteritems() if v is blah][0]

Python 3+

blah = 1
blah_name = [ k for k,v in locals().items() if v is blah][0]
Dipetalous answered 26/6, 2011 at 18:50 Comment(5)
@Dipetalous I liked this approach very much and have used it from time to time now. However I cant get it to work inside functions. I guess there are "better" ways to do it, but none are as nice'n'simple as nbubis puts it. Have you been able to use it in functions keflavich? This is where I ask a question about this.Stabler
Note that in Python 3, iteritems() is replaced by items()Wellfed
This is unreliable: spam = 1; blah = 1; blah_name = [ k for k,v in locals().items() if v is blah][0]; print(blah_name) Outputs spamNozicka
@Nozicka that is because spam = 1, blah = 1; assert spam is blah. The solution breaks when comparing primitive data types.Pothunter
@Pothunter The solution breaks whenever you have two or more variables mapping to the same object. This could be any object (ints, dicts, class objects, classes, functions, etc.), not just when you are dealing with primitive data types.Cambium
H
47

Are you trying to do this?

dict( (name,eval(name)) for name in ['some','list','of','vars'] )

Example

>>> some= 1
>>> list= 2
>>> of= 3
>>> vars= 4
>>> dict( (name,eval(name)) for name in ['some','list','of','vars'] )
{'list': 2, 'some': 1, 'vars': 4, 'of': 3}
Hooten answered 31/3, 2010 at 13:59 Comment(10)
Nice one S.Lott. Never far away from a Python question, ain't you? This is the closest we can get I guess, given that we apparently can't get access to the many names that point to a variable value. Not totally automatic, but close enough.Pteryla
@e-satis: What could be more automatic than this? What are you talking about? All variables are already in locals.Hooten
rlotun is closer to the initial "spirit" of it since it allows to discover the name. I will could use both your anwser. Or maybe just use my damn hand to type. Some things are just not made to be that automatized...Pteryla
@e-satis: For @rlotun's to work, you have to provide the list of variables. If you have the list of variables, what's the point of "discovering" their names?Hooten
Why eval instead of explicitly using locals and globals?Karlin
@Roger Pate: Because I couldn't figure out what the point of the whole exercise was.Hooten
This answer does not answer the question asked. If you have the list of variables, what's the point of "discovering" their names? To avoid duplication so that instead of print('x: ' + x) one could write magic_print(x) and have the same output without writing variable's name twice.Semidome
@PiotrDobrogost: have you found a way to do it? Great point by the way! My attempts to build your magic_print led me to the question in the first place.Stabler
@Hooten The "point" in my case is quite simple: I'd rather read foo in a log than '<function foo at 0x7f08ba9ad400>' I have a queue that holds method calls + arguments for delayed execution, and I'd like to log the name of the method about to be called.Solarize
@PiotrDobrogost That follows from this answer: def magic_print(x): print("%s: %s" % (x, eval(x)) then magic_print('x'). If you don't know the variable name, see #545419Serrulation
H
17

This is a hack. It will not work on all Python implementations distributions (in particular, those that do not have traceback.extract_stack.)

import traceback

def make_dict(*expr):
    (filename,line_number,function_name,text)=traceback.extract_stack()[-2]
    begin=text.find('make_dict(')+len('make_dict(')
    end=text.find(')',begin)
    text=[name.strip() for name in text[begin:end].split(',')]
    return dict(zip(text,expr))

bar=True
foo=False
print(make_dict(bar,foo))
# {'foo': False, 'bar': True}

Note that this hack is fragile:

make_dict(bar,
          foo)

(calling make_dict on 2 lines) will not work.

Instead of trying to generate the dict out of the values foo and bar, it would be much more Pythonic to generate the dict out of the string variable names 'foo' and 'bar':

dict([(name,locals()[name]) for name in ('foo','bar')])
Humpbacked answered 31/3, 2010 at 13:58 Comment(2)
+1 for the smart hack. Of course, trace back are very slow so it may be slugish to use it.Pteryla
+1111111!!!! Yeah it's slow, but when using to replace print("a_very_long_name: {}'.format(a_very_long_name)) who cares!Acetic
E
14

This is not possible in Python, which really doesn't have "variables". Python has names, and there can be more than one name for the same object.

Engine answered 31/3, 2010 at 13:44 Comment(1)
yeah, I know, I made the question simple, but I was expecting more something like "get_var_tags(var)[0]".Pteryla
L
10

I think my problem will help illustrate why this question is useful, and it may give a bit more insight into how to answer it. I wrote a small function to do a quick inline head check on various variables in my code. Basically, it lists the variable name, data type, size, and other attributes, so I can quickly catch any mistakes I've made. The code is simple:

def details(val):
  vn = val.__name__                 #  If such a thing existed
  vs = str(val)
  print("The Value of "+ str(vn) + " is " + vs)
  print("The data type of " + vn + " is " + str(type(val)))

So if you have some complicated dictionary / list / tuple situation, it would be quite helpful to have the interpreter return the variable name you assigned. For instance, here is a weird dictionary:

m = 'abracadabra'
mm=[]    
for n in m:
  mm.append(n)
mydic = {'first':(0,1,2,3,4,5,6),'second':mm,'third':np.arange(0.,10)}



details(mydic)

The Value of mydic is {'second': ['a', 'b', 'r', 'a', 'c', 'a', 'd', 'a', 'b', 'r', 'a'], 'third': array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.]), 'first': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}
The data type of mydic is <type 'dict'>

details(mydic['first'])
The Value of mydic['first'] is (0, 1, 2, 3, 4, 5, 6)]
The data type of mydic['first'] is <type 'list'>

details(mydic.keys())
The Value of mydic.keys() is ['second', 'third', 'first']
The data type of mydic.keys() is <type 'tuple'>

details(mydic['second'][0])
The Value of mydic['second'][0] is a
The data type of mydic['second'][0] is <type 'str'>

I'm not sure if I put this in the right place, but I thought it might help. I hope it does.

Ludmilla answered 3/6, 2013 at 21:42 Comment(1)
So with your head check, does it account for the fact that variables/names can be pointing to different things at different times in the code? For instance myconnection could be pointing to a boolean value at one point, an integer at another time, and a socket connection at another point in code execution??Fulgurite
H
9

I wrote a neat little useful function based on the answer to this question. I'm putting it here in case it's useful.

def what(obj, callingLocals=locals()):
    """
    quick function to print name of input and value. 
    If not for the default-Valued callingLocals, the function would always
    get the name as "obj", which is not what I want.    
    """
    for k, v in list(callingLocals.items()):
         if v is obj:
            name = k
    print(name, "=", obj)

usage:

>> a = 4
>> what(a)
a = 4
>>|
Hegelianism answered 21/5, 2017 at 21:37 Comment(0)
B
6

I find that if you already have a specific list of values, that the way described by @S. Lotts is the best; however, the way described below works well to get all variables and Classes added throughout the code WITHOUT the need to provide variable name though you can specify them if you want. Code can be extend to exclude Classes.

import types
import math  # mainly showing that you could import what you will before d

# Everything after this counts
d = dict(globals())

def kv_test(k,v):
    return (k not in d and 
            k not in ['d','args'] and
            type(v) is not types.FunctionType)

def magic_print(*args):
    if len(args) == 0: 
        return {k:v for k,v in globals().iteritems() if kv_test(k,v)}
    else:
        return {k:v for k,v in magic_print().iteritems() if k in args}

if __name__ == '__main__':
    foo = 1
    bar = 2
    baz = 3
    print magic_print()
    print magic_print('foo')
    print magic_print('foo','bar')

Output:

{'baz': 3, 'foo': 1, 'bar': 2}
{'foo': 1}
{'foo': 1, 'bar': 2}
Bronchiole answered 6/11, 2013 at 23:31 Comment(0)
O
6

In python 3 this is easy

myVariable = 5
for v in locals():
  if id(v) == id("myVariable"):
    print(v, locals()[v])

this will print:

myVariable 5

Ontine answered 4/3, 2014 at 20:40 Comment(5)
This is similar to rlotun's approach but a bit simplierOntine
-1. Open a new interpreter window and try for v in locals().Scuppernong
I'm not totally sure what you mean?Ontine
This will give an error: RuntimeError: dictionary changed size during iteration...Axilla
however you can do for v in list(locals()):Oleum
P
5

Python3. Use inspect to capture the calling local namespace then use ideas presented here. Can return more than one answer as has been pointed out.

def varname(var):
  import inspect
  frame = inspect.currentframe()
  var_id = id(var)
  for name in frame.f_back.f_locals.keys():
    try:
      if id(eval(name)) == var_id:
        return(name)
    except:
      pass
Pirozzo answered 30/8, 2015 at 23:43 Comment(1)
Good answer, but for me it is better with : ... id(eval(name, None, frame.f_back.f_locals)) == ...Trumpetweed
P
5

Here's the function I created to read the variable names. It's more general and can be used in different applications:

def get_variable_name(*variable):
    '''gets string of variable name
    inputs
        variable (str)
    returns
        string
    '''
    if len(variable) != 1:
        raise Exception('len of variables inputed must be 1')
    try:
        return [k for k, v in locals().items() if v is variable[0]][0]
    except:
        return [k for k, v in globals().items() if v is variable[0]][0]

To use it in the specified question:

>>> foo = False
>>> bar = True
>>> my_dict = {get_variable_name(foo):foo, 
               get_variable_name(bar):bar}
>>> my_dict
{'bar': True, 'foo': False}
Pyrazole answered 5/12, 2016 at 18:10 Comment(0)
L
4

In reading the thread, I saw an awful lot of friction. It's easy enough to give a bad answer, then let someone give the correct answer. Anyway, here is what I found.

From: [effbot.org] (http://effbot.org/zone/python-objects.htm#names)

The names are a bit different — they’re not really properties of the object, and the object itself doesn't know what it’s called.

An object can have any number of names, or no name at all.

Names live in namespaces (such as a module namespace, an instance namespace, a function’s local namespace).

Note: that it says the object itself doesn’t know what it’s called, so that was the clue. Python objects are not self-referential. Then it says, Names live in namespaces. We have this in TCL/TK. So maybe my answer will help (but it did help me)


    jj = 123
    print eval("'" + str(id(jj)) + "'")
    print dir()

166707048
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'jj']

So there is 'jj' at the end of the list.

Rewrite the code as:


    jj = 123
    print eval("'" + str(id(jj)) + "'")
    for x in dir():
        print id(eval(x))

161922920
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'jj']
3077447796
136515736
3077408320
3077656800
136515736
161922920

This nasty bit of code id's the name of variable/object/whatever-you-pedantics-call-it.

So, there it is. The memory address of 'jj' is the same when we look for it directly, as when we do the dictionary look up in global name space. I'm sure you can make a function to do this. Just remember which namespace your variable/object/wypci is in.

QED.

Licensee answered 12/4, 2012 at 2:56 Comment(1)
You have two crazy uses of eval here. The first is exactly the same as: print id(jj). The second simply looks up the name, and can be done more easily with vars().Flaxen
M
3

I wrote the package sorcery to do this kind of magic robustly. You can write:

from sorcery import dict_of

my_dict = dict_of(foo, bar)
Maddux answered 15/7, 2018 at 11:35 Comment(0)
N
2

Maybe I'm overthinking this but..

str_l = next((k for k,v in locals().items() if id(l) == id(v)))


>>> bar = True
>>> foo = False
>>> my_dict=dict(bar=bar, foo=foo)
>>> next((k for k,v in locals().items() if id(bar) == id(v)))
'bar'
>>> next((k for k,v in locals().items() if id(foo) == id(v)))
'foo'
>>> next((k for k,v in locals().items() if id(my_dict) == id(v)))
'my_dict'
Naphtha answered 16/8, 2013 at 3:56 Comment(1)
Great! This is what I was looking for. Thanks @rh0dium...\n variable = 1 \n [k for k,v in locals().items() if id(variable) == id(v)] \n Out[14]: ['variable']Subservient
G
2
import re
import traceback

pattren = re.compile(r'[\W+\w+]*get_variable_name\((\w+)\)')
def get_variable_name(x):
    return pattren.match( traceback.extract_stack(limit=2)[0][3]) .group(1)

a = 1
b = a
c = b
print get_variable_name(a)
print get_variable_name(b)
print get_variable_name(c)
Granddaughter answered 18/9, 2016 at 12:46 Comment(0)
A
2

I uploaded a solution to pypi. It's a module defining an equivalent of C#'s nameof function.

It iterates through bytecode instructions for the frame its called in, getting the names of variables/attributes passed to it. The names are found in the .argrepr of LOAD instructions following the function's name.

Awful answered 22/1, 2018 at 14:36 Comment(0)
K
1

Most objects don't have a __name__ attribute. (Classes, functions, and modules do; any more builtin types that have one?)

What else would you expect for print(my_var.__name__) other than print("my_var")? Can you simply use the string directly?

You could "slice" a dict:

def dict_slice(D, keys, default=None):
  return dict((k, D.get(k, default)) for k in keys)

print dict_slice(locals(), ["foo", "bar"])
# or use set literal syntax if you have a recent enough version:
print dict_slice(locals(), {"foo", "bar"})

Alternatively:

throw = object()  # sentinel
def dict_slice(D, keys, default=throw):
  def get(k):
    v = D.get(k, throw)
    if v is not throw:
      return v
    if default is throw:
      raise KeyError(k)
    return default
  return dict((k, get(k)) for k in keys)
Karlin answered 31/3, 2010 at 13:46 Comment(2)
+1 but I know that name doesn't exist, why does everybody take this "something like" litteraly? Your solution doesn't solve the problem since I don't want to harcode the name, overwise I would do the dict solution I already gave in the question.Pteryla
@e-satis: If simply using everything in locals() solves your problem, I have no idea what you're asking. I'm guessing you're okay with calling some_func(var), so I tried to point out there's not very far from some_func("var"), with dictslice allowing you to get the name-value mapping for multiple variables at once.Karlin
R
1

Well, I encountered the very same need a few days ago and had to get a variable's name which was pointing to the object itself.

And why was it so necessary?

In short I was building a plug-in for Maya. The core plug-in was built using C++ but the GUI is drawn through Python(as its not processor intensive). Since I, as yet, don't know how to return multiple values from the plug-in except the default MStatus, therefore to update a dictionary in Python I had to pass the the name of the variable, pointing to the object implementing the GUI and which contained the dictionary itself, to the plug-in and then use the MGlobal::executePythonCommand() to update the dictionary from the global scope of Maya.

To do that what I did was something like:

import time

class foo(bar):

    def __init__(self):
        super(foo, self).__init__()
        self.time = time.time() #almost guaranteed to be unique on a single computer

    def name(self):
        g = globals()
        for x in g:
            if isinstance(g[x], type(self)):
                if g[x].time == self.time:
                    return x
                    #or you could:
                    #return filter(None,[x if g[x].time == self.time else None for x in g if isinstance(g[x], type(self))])
                    #and return all keys pointing to object itself

I know that it is not the perfect solution in in the globals many keys could be pointing to the same object e.g.:

a = foo()
b = a
b.name()
>>>b
or
>>>a

and that the approach isn't thread-safe. Correct me if I am wrong.

At least this approach solved my problem by getting the name of any variable in the global scope which pointed to the object itself and pass it over to the plug-in, as argument, for it use internally.

I tried this on int (the primitive integer class) but the problem is that these primitive classes don't get bypassed (please correct the technical terminology used if its wrong). You could re-implement int and then do int = foo but a = 3 will never be an object of foo but of the primitive. To overcome that you have to a = foo(3) to get a.name() to work.

Ration answered 5/9, 2012 at 19:3 Comment(0)
A
1

With python 2.7 and newer there is also dictionary comprehension which makes it a bit shorter. If possible I would use getattr instead eval (eval is evil) like in the top answer. Self can be any object which has the context your a looking at. It can be an object or locals=locals() etc.

{name: getattr(self, name) for name in ['some', 'vars', 'here]}
Audet answered 9/2, 2013 at 7:11 Comment(0)
M
1

I was working on a similar problem. @S.Lott said "If you have the list of variables, what's the point of "discovering" their names?" And my answer is just to see if it could be done and if for some reason you want to sort your variables by type into lists. So anyways, in my research I came came across this thread and my solution is a bit expanded and is based on @rlotun solution. One other thing, @unutbu said, "This idea has merit, but note that if two variable names reference the same value (e.g. True), then an unintended variable name might be returned." In this exercise that was true so I dealt with it by using a list comprehension similar to this for each possibility: isClass = [i for i in isClass if i != 'item']. Without it "item" would show up in each list.

__metaclass__ = type

from types import *

class Class_1: pass
class Class_2: pass
list_1 = [1, 2, 3]
list_2 = ['dog', 'cat', 'bird']
tuple_1 = ('one', 'two', 'three')
tuple_2 = (1000, 2000, 3000)
dict_1 = {'one': 1, 'two': 2, 'three': 3}
dict_2 = {'dog': 'collie', 'cat': 'calico', 'bird': 'robin'}
x = 23
y = 29
pie = 3.14159
eee = 2.71828
house = 'single story'
cabin = 'cozy'

isClass = []; isList = []; isTuple = []; isDict = []; isInt = []; isFloat = []; isString = []; other = []

mixedDataTypes = [Class_1, list_1, tuple_1, dict_1, x, pie, house, Class_2, list_2, tuple_2, dict_2, y, eee, cabin]

print '\nMIXED_DATA_TYPES total count:', len(mixedDataTypes)

for item in mixedDataTypes:
    try:
        # if isinstance(item, ClassType): # use this for old class types (before 3.0)
        if isinstance(item, type):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isClass.append(mapping_as_str)
            isClass = [i for i in isClass if i != 'item']

        elif isinstance(item, ListType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isList.append(mapping_as_str)
            isList = [i for i in isList if i != 'item']

        elif isinstance(item, TupleType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isTuple.append(mapping_as_str)
            isTuple = [i for i in isTuple if i != 'item']

        elif isinstance(item, DictType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isDict.append(mapping_as_str)
            isDict = [i for i in isDict if i != 'item']

        elif isinstance(item, IntType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isInt.append(mapping_as_str)
            isInt = [i for i in isInt if i != 'item']

        elif isinstance(item, FloatType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isFloat.append(mapping_as_str)
            isFloat = [i for i in isFloat if i != 'item']

        elif isinstance(item, StringType):
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    isString.append(mapping_as_str)
            isString = [i for i in isString if i != 'item']

        else:
            for k, v in list(locals().iteritems()):
                if v is item:
                    mapping_as_str = k
                    other.append(mapping_as_str)
            other = [i for i in other if i != 'item']

    except (TypeError, AttributeError), e:
        print e

print '\n isClass:', len(isClass), isClass
print '  isList:', len(isList), isList
print ' isTuple:', len(isTuple), isTuple
print '  isDict:', len(isDict), isDict
print '   isInt:', len(isInt), isInt
print ' isFloat:', len(isFloat), isFloat
print 'isString:', len(isString), isString
print '   other:', len(other), other

# my output and the output I wanted
'''
MIXED_DATA_TYPES total count: 14

 isClass: 2 ['Class_1', 'Class_2']
  isList: 2 ['list_1', 'list_2']
 isTuple: 2 ['tuple_1', 'tuple_2']
  isDict: 2 ['dict_1', 'dict_2']
   isInt: 2 ['x', 'y']
 isFloat: 2 ['pie', 'eee']
isString: 2 ['house', 'cabin']
   other: 0 []
'''
Minutia answered 1/9, 2013 at 12:19 Comment(2)
The issue I'd take with this is that names are not properties of objects. A single object may have multiple names, or no name at all. For instance, you you added pi = pie to your code, you'd get an extra entry in your isFloat list. If you added tuple_1[0] to your mixedDataTypes list, no name will be found for it despite "one" being in your code twice (though thanks to string interning, they'll both be references to the same object).Maimaia
@Maimaia --- I agree. This is just another way to do something that really wasn't meant to be done. I didn't say it renders unique results or that it's infallible. In doing this I found out that using pi and e as variables caused unwanted output and that's because both are part of the math library. For me this was just an exercise to see if it could be done even though the end result isn't perfect. In my learning of this language going through books only goes so far. In my opinion, if you really want to learn the language then you have to play "what if" and see what you come up with.Minutia
J
1

you can use easydict

>>> from easydict import EasyDict as edict
>>> d = edict({'foo':3, 'bar':{'x':1, 'y':2}})
>>> d.foo
3
>>> d.bar.x
1
>>> d = edict(foo=3)
>>> d.foo
3

another example:

>>> d = EasyDict(log=False)
>>> d.debug = True
>>> d.items()
[('debug', True), ('log', False)]
Juxon answered 30/6, 2016 at 9:53 Comment(0)
M
1

On python3, this function will get the outer most name in the stack:

import inspect


def retrieve_name(var):
        """
        Gets the name of var. Does it from the out most frame inner-wards.
        :param var: variable to get name from.
        :return: string
        """
        for fi in reversed(inspect.stack()):
            names = [var_name for var_name, var_val in fi.frame.f_locals.items() if var_val is var]
            if len(names) > 0:
                return names[0]

It is useful anywhere on the code. Traverses the reversed stack looking for the first match.

Middlebreaker answered 17/9, 2016 at 23:19 Comment(0)
O
0

While this is probably an awful idea, it is along the same lines as rlotun's answer but it'll return the correct result more often.

import inspect
def getVarName(getvar):
  frame = inspect.currentframe()
  callerLocals = frame.f_back.f_locals
  for k, v in list(callerLocals.items()):
    if v is getvar():
      callerLocals.pop(k)
      try:
        getvar()
        callerLocals[k] = v
      except NameError:
        callerLocals[k] = v
        del frame
        return k
  del frame

You call it like this:

bar = True
foo = False
bean = False
fooName = getVarName(lambda: foo)
print(fooName) # prints "foo"
Oleum answered 21/12, 2017 at 23:16 Comment(0)
C
0

should get list then return

def get_var_name(**kwargs):
    """get variable name
        get_var_name(var = var)
    Returns:
        [str] -- var name
    """
    return list(kwargs.keys())[0]
Czardom answered 31/5, 2018 at 1:8 Comment(0)
C
0

It will not return the name of variable but you can create dictionary from global variable easily.

class CustomDict(dict):
    def __add__(self, other):
        return CustomDict({**self, **other})

class GlobalBase(type):
    def __getattr__(cls, key):
        return CustomDict({key: globals()[key]})

    def __getitem__(cls, keys):
        return CustomDict({key: globals()[key] for key in keys})

class G(metaclass=GlobalBase):
    pass

x, y, z = 0, 1, 2

print('method 1:', G['x', 'y', 'z']) # Outcome: method 1: {'x': 0, 'y': 1, 'z': 2}
print('method 2:', G.x + G.y + G.z) # Outcome: method 2: {'x': 0, 'y': 1, 'z': 2}
Courtesan answered 13/1, 2020 at 18:13 Comment(0)
A
0

With python-varname you can easily do it:

pip install python-varname

from varname import Wrapper

foo = Wrapper(True)
bar = Wrapper(False)

your_dict = {val.name: val.value for val in (foo, bar)}

print(your_dict)

# {'foo': True, 'bar': False}

Disclaimer: I'm the author of that python-varname library.

Ajar answered 20/4, 2020 at 19:17 Comment(0)
B
-1
>>> a = 1
>>> b = 1
>>> id(a)
34120408
>>> id(b)
34120408
>>> a is b
True
>>> id(a) == id(b)
True

this way get varname for a maybe 'a' or 'b'.

Bindweed answered 19/10, 2016 at 12:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.