Simpler way to create dictionary of separate varia

2018-12-31 05:34发布

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 vars 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.

25条回答
有味是清欢
2楼-- · 2018-12-31 05:52

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
>>|
查看更多
还给你的自由
3楼-- · 2018-12-31 05:54

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.

查看更多
泛滥B
4楼-- · 2018-12-31 05:54

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"
查看更多
宁负流年不负卿
5楼-- · 2018-12-31 05:55

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)
查看更多
路过你的时光
6楼-- · 2018-12-31 06:01
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)
查看更多
后来的你喜欢了谁
7楼-- · 2018-12-31 06:01
>>> 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'.

查看更多
登录 后发表回答