Getting the name of a variable as a string

前端 未结 23 2657
旧时难觅i
旧时难觅i 2020-11-22 00:19

This thread discusses how to get the name of a function as a string in Python: How to get a function name as a string?

How can I do the same for a variable? As oppose

相关标签:
23条回答
  • 2020-11-22 00:58

    Even if variable values don't point back to the name, you have access to the list of every assigned variable and its value, so I'm astounded that only one person suggested looping through there to look for your var name.

    Someone mentioned on that answer that you might have to walk the stack and check everyone's locals and globals to find foo, but if foo is assigned in the scope where you're calling this retrieve_name function, you can use inspect's current frame to get you all of those local variables.

    My explanation might be a little bit too wordy (maybe I should've used a "foo" less words), but here's how it would look in code (Note that if there is more than one variable assigned to the same value, you will get both of those variable names):

    import inspect
    
    x,y,z = 1,2,3
    
    def retrieve_name(var):
        callers_local_vars = inspect.currentframe().f_back.f_locals.items()
        return [var_name for var_name, var_val in callers_local_vars if var_val is var]
    
    print retrieve_name(y)
    

    If you're calling this function from another function, something like:

    def foo(bar):
        return retrieve_name(bar)
    
    foo(baz)
    

    And you want the baz instead of bar, you'll just need to go back a scope further. This can be done by adding an extra .f_back in the caller_local_vars initialization.

    See an example here: ideone

    0 讨论(0)
  • 2020-11-22 01:01

    In Python, the def and class keywords will bind a specific name to the object they define (function or class). Similarly, modules are given a name by virtue of being called something specific in the filesystem. In all three cases, there's an obvious way to assign a "canonical" name to the object in question.

    However, for other kinds of objects, such a canonical name may simply not exist. For example, consider the elements of a list. The elements in the list are not individually named, and it is entirely possible that the only way to refer to them in a program is by using list indices on the containing list. If such a list of objects was passed into your function, you could not possibly assign meaningful identifiers to the values.

    Python doesn't save the name on the left hand side of an assignment into the assigned object because:

    1. It would require figuring out which name was "canonical" among multiple conflicting objects,
    2. It would make no sense for objects which are never assigned to an explicit variable name,
    3. It would be extremely inefficient,
    4. Literally no other language in existence does that.

    So, for example, functions defined using lambda will always have the "name" <lambda>, rather than a specific function name.

    The best approach would be simply to ask the caller to pass in an (optional) list of names. If typing the '...','...' is too cumbersome, you could accept e.g. a single string containing a comma-separated list of names (like namedtuple does).

    0 讨论(0)
  • 2020-11-22 01:01

    Maybe this could be useful:

    def Retriever(bar):
        return (list(globals().keys()))[list(map(lambda x: id(x), list(globals().values()))).index(id(bar))]
    

    The function goes through the list of IDs of values from the global scope (the namespace could be edited), finds the index of the wanted/required var or function based on its ID, and then returns the name from the list of global names based on the acquired index.

    0 讨论(0)
  • 2020-11-22 01:01

    For constants, you can use an enum, which supports retrieving its name.

    0 讨论(0)
  • 2020-11-22 01:01

    I try to get name from inspect locals, but it cann't process var likes a[1], b.val. After it, I got a new idea --- get var name from the code, and I try it succ! code like below:

    #direct get from called function code
    def retrieve_name_ex(var):
        stacks = inspect.stack()
        try:
            func = stacks[0].function
            code = stacks[1].code_context[0]
            s = code.index(func)
            s = code.index("(", s + len(func)) + 1
            e = code.index(")", s)
            return code[s:e].strip()
        except:
            return ""
    
    0 讨论(0)
提交回复
热议问题