1

Say I had these variables defined

a=1
b="2"
c=2
d=2
e="2"

I need a way to get all of the variable names that could be paired with an object I specify. For example, if I specify "2", it should return ["b","e"] because those are the two variables with the value "2". If I specify the integer 2, it should give me ["c","d"]. Is there a way to do this? I am looking for a pythonic answer as well.

Qwerty
  • 1,252
  • 1
  • 11
  • 23
  • 1
    Any reason you can't use a dict? (`myobjects['a'] = 1`, `myobjects['b'] = "2"`, etc.) This will be much easier to work with. – glibdud Feb 12 '18 at 20:18
  • There is no pythonic way to do this, you'll have to check all possible name:object pairs in all possible namespaces to get a general answer. If you can retrict to a name-space, e.g. `globals` then you can just check that namespace. In general, you shouldn't rely on this sort of thing, unless you are building a debugger or soemthing – juanpa.arrivillaga Feb 12 '18 at 20:25
  • @juanpa.arrivillaga the duplicate you marked has almost nothing to do with the question I asked – Qwerty Feb 12 '18 at 20:31
  • @Qwerty of course it does, it is about retrieving variable names as strings from an object. – juanpa.arrivillaga Feb 12 '18 at 20:33
  • @juanpa.arrivillaga it is not a duplicate because that question does not have the answer to my question – Qwerty Feb 12 '18 at 20:35
  • Yes, *it does*. What about the (several) answers doesn't answer your question? – juanpa.arrivillaga Feb 12 '18 at 20:35
  • I don't want to just give a variable and get the variables name as a string, I want to get all possible variable names that could be the pair of an object I specify in the form of a list. @juanpa.arrivillaga – Qwerty Feb 12 '18 at 20:37
  • That is *exactly* what is addressed in the answers. And in my comment. – juanpa.arrivillaga Feb 12 '18 at 20:37
  • @juanpa.arrivillaga I must admit the answers were very far from my own, I understand OP remarks, but hey 1) OP question is answered 2) I'm not going to reopen out of respect for you and 3) 5 upvotes is already nice (for a non-duplicate :)). Last time some answerer reopened a question I closed, the duplicate was even more blatant, and he got slapped!! – Jean-François Fabre Feb 12 '18 at 20:58
  • @Jean-FrançoisFabre there are various answers that involve searching the call stack, in both orders, which would arrive at `locals` and `globals` eventually, your answer just specifically only looks at `locals` or `globals`, but names could exist in other blocks. Your answer essentially hard-codes the local scope and the global scope and ignores other blocks, which might be fine for whatever the OP is trying to accomplish, although I suspect it is an XY-problem to begin with. – juanpa.arrivillaga Feb 12 '18 at 21:05
  • I think that most of the time, when you want to do such a thing (which is questionnable, yes, because you get all the garbage variables along), you probably care about variables that you can access in the current scope. but glibdud first comment was spot on: just store the variables you want to keep in a dict. Unless you're maintaining someone else horrible code / debug it. – Jean-François Fabre Feb 12 '18 at 21:08
  • one valid usage for instance would be: someone forgot a `print(z)`, so the code is constantly displaying "12.0" many times per second, but from where? In that case I admit that scanning all function scopes would be better. – Jean-François Fabre Feb 12 '18 at 21:09

1 Answers1

5

for global variables, scan the globals() dictionary and extract the variable with the value you're looking for:

a=1
b="2"
c=2
d=2
e="2"

print([k for k,v in globals().items() if v=="2"])

result:

['e', 'b']

same goes for locals using locals(). To test locals & globals, chain both dict items and use a set because values repeat depending on the scope:

{k for k,v in itertools.chain(locals().items(),globals().items()) if v=="2"}
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219