Can I print original variable's name in Python

2019-01-01 09:32发布

I have enum and use the variables like myEnum.SomeNameA, myEnum.SomeNameB, etc. When I return one of these variables from a function, can I print their names (such as myEnum.SomeNameA) instead of the value they returned?

10条回答
梦寄多情
2楼-- · 2019-01-01 09:40

There are two answers to this question: Yes and No.

Can you do it?  -- Yes (in most cases)
Is it worth it? -- No  (in most cases)

How to do it:

It depends on an implementation of enums. For example:

class Enum:
    A = 1
    B = 2

It doesn't matter whether there are 100 names refers to an integer whose name you'd like to find if you know enums class object and all they're names (or at least a unique prefix) in that class.

For the example above as @batbrat suggested you can inspect 'Enum.__dict__' using namestr():

 >>> getEnum = lambda: Enum.A
 >>> namestr(getEnum(), Enum.__dict__)
 >>> ['A']

In this case you even don't have to know all enum names. If enums implemented differently then you might need to use a different hack. There will be some solution in most cases e.g., see @Jay's answer. But it doesn't matter because..

Is it worth it?

  • Some enum implementations may require ugly, complex and in the end unreliable hacks to implement namestr().

  • Enum class can return answer by itself (see @David's, @Ber's, @gahooa's answers).

  • As @Ber pointed out there is no builtin Enum and switch statement in Python (see PEP-0275, PEP-3103). It is worth investigating solutions without enums.

查看更多
孤独总比滥情好
3楼-- · 2019-01-01 09:41

As far as I know, that will require some introspection. You can try using the inspect module.

There are a few simple things you may want to try before that:

  1. This is not the exact code that should be used. You will have to retrieve the variable name from __dict__ before printing.
    print myEnum.__dict__
            
  2. If you want to print the variable name from inside the function, you can try the functions - vars(), locals() and globals().
    Edit:
    I just noticed that this is not what you want. In that case adding a dict and a function may work
  3. You may want to print the __dict__ of the class of your enums.

All that said, there aren't standard enumerations in Python. It would help to know how you are creating them.

On second thoughts, you can maintain your variables as a dictionary in the enum, keyed by variable name and provide a method of the enumeration to find the right variable and print its name. This solution (keeping a dict) is bad because variable values aren't necessarily unique.

Edit:
The problem is not trivial, so you may want to use a tried and tested solution. IMHO, you would be better off avoiding the situation if you can.

查看更多
梦寄多情
4楼-- · 2019-01-01 09:45

On second thought:

Since Python does not provide native Enum types, you should not ask for one, but instead use other, more powerful construct to build your program. Otherwise, the next step will invariably be "Why does Python not have a switch ...: statement, and how do I best emulate it?"

Since Enums are often used to define some kind of state, a much better approach is this: Create a base class that define all the abstract properties, attributes and methods belonging to a state. Then, for each state, derive a sub class that implements the specific behavior of this state. You can then pass around these classes (or maybe instances thereof) to handle the state and its behaviour.

If you use classes instead of instances (the Python way of a "singleton"), you can simply check for any given state (not that it should be necessary) by if current_state is StateA: (note the is instead of ==) with no performance penalty over comparing integer values.

And of course, you can define a name attribute and a __str__() method to access and print the state's name.

查看更多
其实,你不懂
5楼-- · 2019-01-01 09:47

There is no such thing as a unique or original variable name http://www.amk.ca/quotations/python-quotes/page-8

The same way as you get the name of that cat you found on your porch: the cat (object) itself cannot tell you its name, and it doesn't really care -- so the only way to find out what it's called is to ask all your neighbours (namespaces) if it's their cat (object)...

....and don't be surprised if you'll find that it's known by many names, or no name at all!

Fredrik Lundh, 3 Nov 2000, in answer to the question "How can I get the name of a variable from C++ when I have the PyObject*?"

查看更多
大哥的爱人
6楼-- · 2019-01-01 09:47

To add to @Jay's answer, some concepts...

Python "variables" are simply references to values. Each value occupies a given memory location (see id())

>>> id(1)
10052552

>>> sys.getrefcount(1)
569

From the above, you may notice that the value "1" is present at the memory location 10052552. It is referred to 569 times in this instance of the interpreter.

>>> MYVAR = 1
>>> sys.getrefcount(1)
570

Now, see that because yet another name is bound to this value, the reference count went up by one.

Based on these facts, it is not realistic/possible to tell what single variable name is pointing to a value.

I think the best way to address your issue is to add a mapping and function to your enum reference back to a string name.

myEnum.get_name(myEnum.SomeNameA) 

Please comment if you would like sample code.

查看更多
倾城一夜雪
7楼-- · 2019-01-01 09:50

You could store the canonical name as an attribute of the instance, and then assign it to a variable with the same name. This might work:

class MyEnum(object):
    def __new__(cls, name):
        try:
            return getattr(MyEnum, name)
        except AttributeError:
            e = super(MyEnum, cls).__new__(cls)
            e.name = name
            setattr(MyEnum, name, e)
            return e

Regardless, it's not a particularly "Pythonic" thing to do.

查看更多
登录 后发表回答