Introspection of a variable name in Python

Is it possible to dynamically determine a variable name in Python?

For example, I sometimes have the following situation:

name = foo if bar else baz type = alpha or bravo D = { "name": name, "type": type } 

It would be nice if the duplication there could be reduced using D = makedict(name, type) .

To some extent, it is sometimes useful for a function to know its own name:

 class Item(object): def item_create(self, item): dispatch("create", item) def item_delete(self, item): dispatch("delete", item) 

Here duplication can be reduced by passing something like __methodname__ instead of explicitly repeating "create" and "delete" respectively. (I suppose you can use a decorator for this, but this seems like an overkill.)

+4
source share
4 answers

In general, you cannot derive a name from a value (there can be no name, there can be several, etc.); when you call your hypothetical makedict(name) , value name is what makedict gets, so (again, in the general case) it cannot distinguish which name (if any) from. You could examine the namespaces of the callers to see if you just hit on a special occasion when the value allows you to output a name (for example, you get 23 ), and only one name in the namespaces of interest that happens to have a value of 23 ! ), but this is clearly a fragile and incorrect architecture. In addition, in your first example, the case is absolutely guaranteed that the special case will not be - the value in name will be exactly the same as in foo or baz , so 100% are sure that the name for this value will be hopelessly ambiguous.

You can use a completely different approach, for example calling makedict('name type', locals()) (passing locals() can clearly be eliminated with the help of dark and deep magic of introspection, but this is not the hardest choice at all) - go to names ( and namespaces, I suggest!) and makedict output the values , which, obviously, is a much stronger sentence (since each name has exactly one meaning, but not vice versa). I.e:.

 def makedict(names, *namespaces): d = {} for n in names.split(): for ns in namespaces: if n in ns: d[n] = ns[n] break else: d[n] = None # or, raise an exception 

If you are interested in digging up namespaces by introspection, rather than just specifying them as callers, look at inspect.getouterframes - but I suggest you reconsider.

The second problem you are raising is completely different (although you could use the inspect functions again to understand the caller name or the function’s own name - what a peculiar idea!). What is common in two cases is that you use an extremely powerful and dangerous mechanism to carry out work that can be done much easier (easier to ensure correctness, easier to debug any problems, easier to test, etc.) - - far from that so that decorators are "redundant", they are far simpler and clearer than your introspection. If you have zillion methods all forms:

 def item_blah(self, item): dispatch("blah", item) 

The easiest way to create them:

 class Item(object): pass def _makedispcall(n): def item_whatever(self, item): dispatch(n, item) item_whatever.__name__ = 'item_' + n return item_whatever for n in 'create delete blah but wait theres more'.split(): setattr(Item, 'item_' + n, _makedispcall(n)) 

Avoiding repetition is a great idea, but runtime introspection is usually not the best way to implement this idea, and Python offers many alternative ways for such an implementation.

+10
source

In general, you cannot do this in Python, because Python has objects, not variables.

If i have

 L1 = [1,2] L2 = L1 

Then L1 and L2 both refer to the same object. He does not have a single name.

Similarly:

 def f1(): pass f2 = f1 

Now the function does not have a single name, and therefore you cannot find out the "name" of the function.

An object in Python can refer to many names - when an object's reference count goes to zero, Python frees memory for it.

+4
source

You can do what you want for functions:

 >>> def blagnorf(): pass >>> print blagnorf.__name__ blagnorf 

But not for variables, unfortunately. Perhaps you could write a preprocessor for your Python code to do this for you, though ...

Note that you can do this in the / Lisp schema using the macro system that they are there.

+1
source

Whenever you get the desire to create simple, simple methods, whose internals depend only on the name of the method, you should probably rethink your interface. Instead, you can do this:

 class Item(object): def item_action(self, action, item): dispatch(action, item) 

where the action can be “create”, “delete”, etc.

+1
source

All Articles