Check if variable exists in Python [duplicate] - python

I want to check if a variable exists. Now I'm doing something like this:
try:
myVar
except NameError:
# Do something.
Are there other ways without exceptions?

To check the existence of a local variable:
if 'myVar' in locals():
# myVar exists.
To check the existence of a global variable:
if 'myVar' in globals():
# myVar exists.
To check if an object has an attribute:
if hasattr(obj, 'attr_name'):
# obj.attr_name exists.

The use of variables that have yet to been defined or set (implicitly or explicitly) is often a bad thing in any language, since it tends to indicate that the logic of the program hasn't been thought through properly, and is likely to result in unpredictable behaviour.
If you need to do it in Python, the following trick, which is similar to yours, will ensure that a variable has some value before use:
try:
myVar
except NameError:
myVar = None # or some other default value.
# Now you're free to use myVar without Python complaining.
However, I'm still not convinced that's a good idea - in my opinion, you should try to refactor your code so that this situation does not occur.
By way of an example, the following code was given below in a comment, to allow line drawing from a previous point to the current point:
if last:
draw(last, current);
last = current
In the case where last has not been bound to a value, that won't help in Python at all since even the checking of last will raise an exception. A better idea would be to ensure last does have a value, one that can be used to decide whether or not it is valid. That would be something like:
last = None
# some time passes ...
if last is not None:
draw(last, current);
last = current
That ensures the variable exists and that you only use it if it's valid for what you need it for. This is what I assume the if last was meant to do in the comment code (but didn't), and you can still add the code to force this if you have no control over the initial setting of the variable, using the exception method above:
# Variable 'last' may or may not be bound to a value at this point.
try:
last
except NameError:
last = None
# It will always now be bound to a value at this point.
if last is not None:
draw(last, current);
last = current

A simple way is to initialize it at first saying myVar = None
Then later on:
if myVar is not None:
# Do something

Using try/except is the best way to test for a variable's existence. But there's almost certainly a better way of doing whatever it is you're doing than setting/testing global variables.
For example, if you want to initialize a module-level variable the first time you call some function, you're better off with code something like this:
my_variable = None
def InitMyVariable():
global my_variable
if my_variable is None:
my_variable = ...

for objects/modules, you can also
'var' in dir(obj)
For example,
>>> class Something(object):
... pass
...
>>> c = Something()
>>> c.a = 1
>>> 'a' in dir(c)
True
>>> 'b' in dir(c)
False

I will assume that the test is going to be used in a function, similar to user97370's answer. I don't like that answer because it pollutes the global namespace. One way to fix it is to use a class instead:
class InitMyVariable(object):
my_variable = None
def __call__(self):
if self.my_variable is None:
self.my_variable = ...
I don't like this, because it complicates the code and opens up questions such as, should this confirm to the Singleton programming pattern? Fortunately, Python has allowed functions to have attributes for a while, which gives us this simple solution:
def InitMyVariable():
if InitMyVariable.my_variable is None:
InitMyVariable.my_variable = ...
InitMyVariable.my_variable = None

catch is called except in Python. other than that it's fine for such simple cases. There's the AttributeError that can be used to check if an object has an attribute.

A way that often works well for handling this kind of situation is to not explicitly check if the variable exists but just go ahead and wrap the first usage of the possibly non-existing variable in a try/except NameError:
# Search for entry.
for x in y:
if x == 3:
found = x
# Work with found entry.
try:
print('Found: {0}'.format(found))
except NameError:
print('Not found')
else:
# Handle rest of Found case here
...

I created a custom function.
def exists(var):
return var in globals()
Then the call the function like follows replacing variable_name with the variable you want to check:
exists("variable_name")
Will return True or False

Like so:
def no(var):
"give var as a string (quote it like 'var')"
assert(var not in vars())
assert(var not in globals())
assert(var not in vars(__builtins__))
import keyword
assert(var not in keyword.kwlist)
Then later:
no('foo')
foo = ....
If your new variable foo is not safe to use, you'll get an AssertionError exception which will point to the line that failed, and then you will know better.
Here is the obvious contrived self-reference:
no('no')
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-88-d14ecc6b025a> in <module>
----> 1 no('no')
<ipython-input-86-888a9df72be0> in no(var)
2 "give var as a string (quote it)"
3 assert( var not in vars())
----> 4 assert( var not in globals())
5 assert( var not in vars(__builtins__))
6 import keyword
AssertionError:

It may not be performant, but you generalise the solution to a function that checks both local variables and global variables.
import inspect
def exists_var(var_name):
frame = inspect.currentframe()
try:
return var_name in frame.f_back.f_locals or var_name in globals()
finally:
del frame
Then you can use it like this:
exists_var('myVar')

Short variant:
my_var = some_value if 'my_var' not in globals() else my_var:

This was my scenario:
for i in generate_numbers():
do_something(i)
# Use the last i.
I can’t easily determine the length of the iterable, and that means that i may or may not exist depending on whether the iterable produces an empty sequence.
If I want to use the last i of the iterable (an i that doesn’t exist for an empty sequence) I can do one of two things:
i = None # Declare the variable.
for i in generate_numbers():
do_something(i)
use_last(i)
or
for i in generate_numbers():
do_something(i)
try:
use_last(i)
except UnboundLocalError:
pass # i didn’t exist because sequence was empty.
The first solution may be problematic because I can’t tell (depending on the sequence values) whether i was the last element. The second solution is more accurate in that respect.

Also a possibility for objects, use __dict__.
class A(object):
def __init__(self):
self.m = 1
a = A()
assert "m" in a.__dict__
assert "k" not in a.__dict__

Related

Redefine `False` in Python2? How to assign a function call to a variable name?

There isn't any reason in particular that I wish to do this, I just wanted to see False be True every once in a while.
import random
def dice():
return random.randint(1,3)==2
False = dice()
This will not give me what I want--I imagine False being initialized to some value as dice() is called, and thus remaining as that value thereon. How can I make it so that each time I check the value of False, it is as if I have called dice()?
If anyone has a better way to phrase this please feel free to provide an edit. Thanks.
To do this, you need more control over the name lookup procedure than Python ordinarily gives you. You need to execute the code in a namespace that uses name lookup rules you control, which means you have to use exec:
import random
class WeirdLocals(dict):
def __getitem__(self, index):
if index == 'False':
return random.choice([True, False])
return super(WeirdLocals, self).__getitem__(index)
exec '''
print False # Might print True
print False # Might print True
print False # Might print True
''' in globals(), WeirdLocals()
Note that functions defined inside an exec will ignore the provided locals for name lookup, and even if you try to provide a global dict with a weird __getitem__ override, they might bypass it anyway.
You cannot do that in either Python 2 or 3. You can assign a value to False in Python 2, but what you can't do is make it so that just reading the value of a plain variable (False or anything else) calls a function.
You can do it if the thing you're reading is not a bare-name variable but some kind of expression (like an attribute access). That is, you can make it so that something like a.b evaluates to a different value every time, but not so that just plain a evaluates to a different value every time.
If you can tolerate having to use . in your variable name, the #property decorator can give you want you want.
Example:
import random
class Foo:
def __init__(self):
pass
#property
def True(self):
return random.choice([True,False,True])
And then if you do
F=Foo()
print(F.True) #will return True 66% of the time and False 33% of
the time.
You can't do that with just False; if you're calling a function, you need to use the function syntax. You could do
False = dice
...
if my_value == False():
... action

Any method to denote object assignment?

I've been studying magic methods in Python, and have been wondering if there's a way to outline the specific action of:
a = MyClass(*params).method()
versus:
MyClass(*params).method()
In the sense that, perhaps, I may want to return a list that has been split on the '\n' character, versus dumping the raw list into the variable a that keeps the '\n' intact.
Is there a way to ask Python if its next action is about to return a value to a variable, and change action, if that's the case? I was thinking:
class MyClass(object):
def __init__(params):
self.end = self.method(*params)
def __asgn__(self):
return self.method(*params).split('\n')
def __str__(self):
"""this is the fallback if __asgn__ is not called"""
return self.method(*params)
No. You cannot change what happens when you assign to a bare name.
You can change what happens if the assignment target on the left hand side is an attribute or item of an object. You can override a[blah] = ... with __setitem__ and a.blah = ... with __setattr__ (although you can only hook into these on a, not on the object being assigned). But you can't override or in any way influence a = ....
Note that having the right-hand side change based on what is "going to happen" would be even stranger, and very bad. That would mean that
someFunc(MyClass().method())
could be different than
a = MyClass().method()
someFunc(a)
In Python names are just labels attached to objects. Objects don't get to know what labels are attached to them, and that's a good thing. You might assign the result a computation to an intermediate variable just to make subsequent lines more readable, and you don't want that assignment to change the result of that computation.
There should be no difference between calling MyClass(*params).method() directly and assigning it to a variable. What you may be seeing here is your interpreter automatically printing return results, which is why it appears to be split while the variable value contains EOL markers.
There is no way to override default assignment to a variable. However, by using an object, you can easily provide your own hooks:
class Assigner(object):
def __init__(self, assignment_callback):
self.assignment = assignment_callback
def __setattr__(self, key, value):
if hasattr(self, 'assignment'):
value = self.assignment(value)
super(Assigner, self).__setattr__( key, value )
def uppercase(value):
# example function to perform on each attribute assignment
return value.upper()
Then in your code, rather than assigning to a variable directly you assign to attributes on your object:
>>> my = Assigner(uppercase)
>>> my.a = 'foo'
>>> print my.a
FOO
Yes.* Python allows inspecting its own stack, which can be used to peek ahead at the next instruction.
#!/usr/bin/env python3
import dis
import inspect
from itertools import dropwhile
class MyClass(object):
def method(self):
# inspect the stack to get calling line of code
frame = inspect.stack()[1].frame
# disassemble stack frame
ins = dis.get_instructions(frame.f_code)
# move to last instruction
ins = dropwhile(lambda x: x.offset < frame.f_lasti, ins)
# the last call would have been to this method/function
current_instruction = ins.__next__()
assert current_instruction.opname.startswith('CALL_')
# peek ahead at the next instruction
next_instruction = ins.__next__()
# vary behaviour depending on the next instruction
if next_instruction.opname.startswith('STORE_'):
return "returning to assignment"
elif next_instruction.opname.startswith('CALL_'):
return "returning to function/method call"
elif next_instruction.opname == 'POP_TOP':
print("return value thrown away")
return "return ignored"
elif next_instruction.opname == 'PRINT_EXPR':
return "return to interactive console"
else:
return "return to {}".format(next_instruction.opname)
This will result in the following behaviour:
a = MyClass().method()
print(a)
# returning to assignment
def someFunc(x):
return x.split()
b = someFunc(MyClass().method())
print(b)
# ['returning', 'to', 'function/method', 'call']
MyClass().method()
# return value thrown away (if called as program)
# return to interactive console (if run interactively)
* Though as the accepted answer points out, doing so is "very bad". It's also fragile, as it can be affected by bytecode optimisation. See also: Nested dictionary that acts as defaultdict when setting items but not when getting items

How to find the name of a variable that was passed to a function?

In C/C++, I have often found it useful while debugging to define a macro, say ECHO(x), that prints out the variable name and its value (i.e. ECHO(variable) might print variable 7). You can get the variable name in a macro using the 'stringification' operator # as described here. Is there a way of doing this in Python?
In other words, I would like a function
def echo(x):
#magic goes here
which, if called as foo=7; echo(foo) (or foo=7; echo('foo'), maybe), would print out foo 7. I realise it is trivial to do this if I pass both the variable and its name to the function, but I use functions like this a lot while debugging, and the repetition always ends up irritating me.
Not really solution, but may be handy (anyway you have echo('foo') in question):
def echo(**kwargs):
for name, value in kwargs.items():
print name, value
foo = 7
echo(foo=foo)
UPDATE: Solution for echo(foo) with inspect
import inspect
import re
def echo(arg):
frame = inspect.currentframe()
try:
context = inspect.getframeinfo(frame.f_back).code_context
caller_lines = ''.join([line.strip() for line in context])
m = re.search(r'echo\s*\((.+?)\)$', caller_lines)
if m:
caller_lines = m.group(1)
print caller_lines, arg
finally:
del frame
foo = 7
bar = 3
baz = 11
echo(foo)
echo(foo + bar)
echo((foo + bar)*baz/(bar+foo))
Output:
foo 7
foo + bar 10
(foo + bar)*baz/(bar+foo) 11
It has the smallest call, but it's sensitive to newlines, e.g.:
echo((foo + bar)*
baz/(bar+foo))
Will print:
baz/(bar+foo)) 11
def echo(x):
import inspect
print "{0}: {1}".format(x, inspect.stack()[1][0].f_locals[x])
y = 123
echo('y')
# 'y: 123'
See also: https://stackoverflow.com/a/2387854/16361
Note that this can cause GC issues:
http://docs.python.org/library/inspect.html#the-interpreter-stack
It will also turn off people who have been burned by messing with frames, and may leave a bad taste in your mouth. But it will work.
Here's a solution that has you type a bit more to call it. It relies on the locals built-in function:
def print_key(dictionary, key):
print key, '=', dictionary[key]
foo = 7
print_key(locals(), 'foo')
An echo with the semantics you mentioned is also possible, using the inspect module. However, do read the warnings in inspect's documentation. This is an ugly non-portable hack (it doesn't work in all implementations of Python). Be sure to only use it for debugging.
The idea is to look into the locals of the calling function. The inspect module allows just that: calls are represented by frame objects linked together by the f_back attribute. Each frame's local and global variables are available (there are also builtins, but you're unlikely to need to print them).
You may want to explicitly delete any references frame objects to prevent reference cycles, as explained in inspect docs, but this is not strictly necessary – the garbage collection will free them sooner or later.
import inspect
def echo(varname):
caller = inspect.currentframe().f_back
try:
value = caller.f_locals[varname]
except KeyError:
value = caller.f_globals[varname]
print varname, '=', value
del caller
foo = 7
echo('foo')

Convert Variable Name to String?

I would like to convert a python variable name into the string equivalent as shown. Any ideas how?
var = {}
print ??? # Would like to see 'var'
something_else = 3
print ??? # Would print 'something_else'
TL;DR: Not possible. See 'conclusion' at the end.
There is an usage scenario where you might need this. I'm not implying there are not better ways or achieving the same functionality.
This would be useful in order to 'dump' an arbitrary list of dictionaries in case of error, in debug modes and other similar situations.
What would be needed, is the reverse of the eval() function:
get_indentifier_name_missing_function()
which would take an identifier name ('variable','dictionary',etc) as an argument, and return a
string containing the identifier’s name.
Consider the following current state of affairs:
random_function(argument_data)
If one is passing an identifier name ('function','variable','dictionary',etc) argument_data to a random_function() (another identifier name), one actually passes an identifier (e.g.: <argument_data object at 0xb1ce10>) to another identifier (e.g.: <function random_function at 0xafff78>):
<function random_function at 0xafff78>(<argument_data object at 0xb1ce10>)
From my understanding, only the memory address is passed to the function:
<function at 0xafff78>(<object at 0xb1ce10>)
Therefore, one would need to pass a string as an argument to random_function() in order for that function to have the argument's identifier name:
random_function('argument_data')
Inside the random_function()
def random_function(first_argument):
, one would use the already supplied string 'argument_data' to:
serve as an 'identifier name' (to display, log, string split/concat, whatever)
feed the eval() function in order to get a reference to the actual identifier, and therefore, a reference to the real data:
print("Currently working on", first_argument)
some_internal_var = eval(first_argument)
print("here comes the data: " + str(some_internal_var))
Unfortunately, this doesn't work in all cases. It only works if the random_function() can resolve the 'argument_data' string to an actual identifier. I.e. If argument_data identifier name is available in the random_function()'s namespace.
This isn't always the case:
# main1.py
import some_module1
argument_data = 'my data'
some_module1.random_function('argument_data')
# some_module1.py
def random_function(first_argument):
print("Currently working on", first_argument)
some_internal_var = eval(first_argument)
print("here comes the data: " + str(some_internal_var))
######
Expected results would be:
Currently working on: argument_data
here comes the data: my data
Because argument_data identifier name is not available in the random_function()'s namespace, this would yield instead:
Currently working on argument_data
Traceback (most recent call last):
File "~/main1.py", line 6, in <module>
some_module1.random_function('argument_data')
File "~/some_module1.py", line 4, in random_function
some_internal_var = eval(first_argument)
File "<string>", line 1, in <module>
NameError: name 'argument_data' is not defined
Now, consider the hypotetical usage of a get_indentifier_name_missing_function() which would behave as described above.
Here's a dummy Python 3.0 code: .
# main2.py
import some_module2
some_dictionary_1 = { 'definition_1':'text_1',
'definition_2':'text_2',
'etc':'etc.' }
some_other_dictionary_2 = { 'key_3':'value_3',
'key_4':'value_4',
'etc':'etc.' }
#
# more such stuff
#
some_other_dictionary_n = { 'random_n':'random_n',
'etc':'etc.' }
for each_one_of_my_dictionaries in ( some_dictionary_1,
some_other_dictionary_2,
...,
some_other_dictionary_n ):
some_module2.some_function(each_one_of_my_dictionaries)
# some_module2.py
def some_function(a_dictionary_object):
for _key, _value in a_dictionary_object.items():
print( get_indentifier_name_missing_function(a_dictionary_object) +
" " +
str(_key) +
" = " +
str(_value) )
######
Expected results would be:
some_dictionary_1 definition_1 = text_1
some_dictionary_1 definition_2 = text_2
some_dictionary_1 etc = etc.
some_other_dictionary_2 key_3 = value_3
some_other_dictionary_2 key_4 = value_4
some_other_dictionary_2 etc = etc.
......
......
......
some_other_dictionary_n random_n = random_n
some_other_dictionary_n etc = etc.
Unfortunately, get_indentifier_name_missing_function() would not see the 'original' identifier names (some_dictionary_,some_other_dictionary_2,some_other_dictionary_n). It would only see the a_dictionary_object identifier name.
Therefore the real result would rather be:
a_dictionary_object definition_1 = text_1
a_dictionary_object definition_2 = text_2
a_dictionary_object etc = etc.
a_dictionary_object key_3 = value_3
a_dictionary_object key_4 = value_4
a_dictionary_object etc = etc.
......
......
......
a_dictionary_object random_n = random_n
a_dictionary_object etc = etc.
So, the reverse of the eval() function won't be that useful in this case.
Currently, one would need to do this:
# main2.py same as above, except:
for each_one_of_my_dictionaries_names in ( 'some_dictionary_1',
'some_other_dictionary_2',
'...',
'some_other_dictionary_n' ):
some_module2.some_function( { each_one_of_my_dictionaries_names :
eval(each_one_of_my_dictionaries_names) } )
# some_module2.py
def some_function(a_dictionary_name_object_container):
for _dictionary_name, _dictionary_object in a_dictionary_name_object_container.items():
for _key, _value in _dictionary_object.items():
print( str(_dictionary_name) +
" " +
str(_key) +
" = " +
str(_value) )
######
In conclusion:
Python passes only memory addresses as arguments to functions.
Strings representing the name of an identifier, can only be referenced back to the actual identifier by the eval() function if the name identifier is available in the current namespace.
A hypothetical reverse of the eval() function, would not be useful in cases where the identifier name is not 'seen' directly by the calling code. E.g. inside any called function.
Currently one needs to pass to a function:
the string representing the identifier name
the actual identifier (memory address)
This can be achieved by passing both the 'string' and eval('string') to the called function at the same time. I think this is the most 'general' way of solving this egg-chicken problem across arbitrary functions, modules, namespaces, without using corner-case solutions. The only downside is the use of the eval() function which may easily lead to unsecured code. Care must be taken to not feed the eval() function with just about anything, especially unfiltered external-input data.
Totally possible with the python-varname package (python3):
from varname import nameof
s = 'Hey!'
print (nameof(s))
Output:
s
Install:
pip3 install varname
Or get the package here:
https://github.com/pwwang/python-varname
I searched for this question because I wanted a Python program to print assignment statements for some of the variables in the program. For example, it might print "foo = 3, bar = 21, baz = 432". The print function would need the variable names in string form. I could have provided my code with the strings "foo","bar", and "baz", but that felt like repeating myself. After reading the previous answers, I developed the solution below.
The globals() function behaves like a dict with variable names (in the form of strings) as keys. I wanted to retrieve from globals() the key corresponding to the value of each variable. The method globals().items() returns a list of tuples; in each tuple the first item is the variable name (as a string) and the second is the variable value. My variablename() function searches through that list to find the variable name(s) that corresponds to the value of the variable whose name I need in string form.
The function itertools.ifilter() does the search by testing each tuple in the globals().items() list with the function lambda x: var is globals()[x[0]]. In that function x is the tuple being tested; x[0] is the variable name (as a string) and x[1] is the value. The lambda function tests whether the value of the tested variable is the same as the value of the variable passed to variablename(). In fact, by using the is operator, the lambda function tests whether the name of the tested variable is bound to the exact same object as the variable passed to variablename(). If so, the tuple passes the test and is returned by ifilter().
The itertools.ifilter() function actually returns an iterator which doesn't return any results until it is called properly. To get it called properly, I put it inside a list comprehension [tpl[0] for tpl ... globals().items())]. The list comprehension saves only the variable name tpl[0], ignoring the variable value. The list that is created contains one or more names (as strings) that are bound to the value of the variable passed to variablename().
In the uses of variablename() shown below, the desired string is returned as an element in a list. In many cases, it will be the only item in the list. If another variable name is assigned the same value, however, the list will be longer.
>>> def variablename(var):
... import itertools
... return [tpl[0] for tpl in
... itertools.ifilter(lambda x: var is x[1], globals().items())]
...
>>> var = {}
>>> variablename(var)
['var']
>>> something_else = 3
>>> variablename(something_else)
['something_else']
>>> yet_another = 3
>>> variablename(something_else)
['yet_another', 'something_else']
as long as it's a variable and not a second class, this here works for me:
def print_var_name(variable):
for name in globals():
if eval(name) == variable:
print name
foo = 123
print_var_name(foo)
>>>foo
this happens for class members:
class xyz:
def __init__(self):
pass
member = xyz()
print_var_name(member)
>>>member
ans this for classes (as example):
abc = xyz
print_var_name(abc)
>>>abc
>>>xyz
So for classes it gives you the name AND the properteries
This is not possible.
In Python, there really isn't any such thing as a "variable". What Python really has are "names" which can have objects bound to them. It makes no difference to the object what names, if any, it might be bound to. It might be bound to dozens of different names, or none.
Consider this example:
foo = 1
bar = 1
baz = 1
Now, suppose you have the integer object with value 1, and you want to work backwards and find its name. What would you print? Three different names have that object bound to them, and all are equally valid.
In Python, a name is a way to access an object, so there is no way to work with names directly. There might be some clever way to hack the Python bytecodes or something to get the value of the name, but that is at best a parlor trick.
If you know you want print foo to print "foo", you might as well just execute print "foo" in the first place.
EDIT: I have changed the wording slightly to make this more clear. Also, here is an even better example:
foo = 1
bar = foo
baz = foo
In practice, Python reuses the same object for integers with common values like 0 or 1, so the first example should bind the same object to all three names. But this example is crystal clear: the same object is bound to foo, bar, and baz.
Technically the information is available to you, but as others have asked, how would you make use of it in a sensible way?
>>> x = 52
>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__',
'x': 52, '__doc__': None, '__package__': None}
This shows that the variable name is present as a string in the globals() dictionary.
>>> globals().keys()[2]
'x'
In this case it happens to be the third key, but there's no reliable way to know where a given variable name will end up
>>> for k in globals().keys():
... if not k.startswith("_"):
... print k
...
x
>>>
You could filter out system variables like this, but you're still going to get all of your own items. Just running that code above created another variable "k" that changed the position of "x" in the dict.
But maybe this is a useful start for you. If you tell us what you want this capability for, more helpful information could possibly be given.
By using the the unpacking operator:
>>> def tostr(**kwargs):
return kwargs
>>> var = {}
>>> something_else = 3
>>> tostr(var = var,something_else=something_else)
{'var' = {},'something_else'=3}
You somehow have to refer to the variable you want to print the name of. So it would look like:
print varname(something_else)
There is no such function, but if there were it would be kind of pointless. You have to type out something_else, so you can as well just type quotes to the left and right of it to print the name as a string:
print "something_else"
What are you trying to achieve? There is absolutely no reason to ever do what you describe, and there is likely a much better solution to the problem you're trying to solve..
The most obvious alternative to what you request is a dictionary. For example:
>>> my_data = {'var': 'something'}
>>> my_data['something_else'] = 'something'
>>> print my_data.keys()
['var', 'something_else']
>>> print my_data['var']
something
Mostly as a.. challenge, I implemented your desired output. Do not use this code, please!
#!/usr/bin/env python2.6
class NewLocals:
"""Please don't ever use this code.."""
def __init__(self, initial_locals):
self.prev_locals = list(initial_locals.keys())
def show_new(self, new_locals):
output = ", ".join(list(set(new_locals) - set(self.prev_locals)))
self.prev_locals = list(new_locals.keys())
return output
# Set up
eww = None
eww = NewLocals(locals())
# "Working" requested code
var = {}
print eww.show_new(locals()) # Outputs: var
something_else = 3
print eww.show_new(locals()) # Outputs: something_else
# Further testing
another_variable = 4
and_a_final_one = 5
print eww.show_new(locals()) # Outputs: another_variable, and_a_final_one
Does Django not do this when generating field names?
http://docs.djangoproject.com/en/dev//topics/db/models/#verbose-field-names
Seems reasonable to me.
I think this is a cool solution and I suppose the best you can get. But do you see any way to handle the ambigious results, your function may return?
As "is" operator behaves unexpectedly with integers shows, low integers and strings of the same value get cached by python so that your variablename-function might priovide ambigous results with a high probability.
In my case, I would like to create a decorator, that adds a new variable to a class by the varialbename i pass it:
def inject(klass, dependency):
klass.__dict__["__"+variablename(dependency)]=dependency
But if your method returns ambigous results, how can I know the name of the variable I added?
var any_var="myvarcontent"
var myvar="myvarcontent"
#inject(myvar)
class myclasss():
def myclass_method(self):
print self.__myvar #I can not be sure, that this variable will be set...
Maybe if I will also check the local list I could at least remove the "dependency"-Variable from the list, but this will not be a reliable result.
Here is a succinct variation that lets you specify any directory.
The issue with using directories to find anything is that multiple variables can have the same value. So this code returns a list of possible variables.
def varname( var, dir=locals()):
return [ key for key, val in dir.items() if id( val) == id( var)]
I don't know it's right or not, but it worked for me
def varname(variable):
for name in list(globals().keys()):
expression = f'id({name})'
if id(variable) == eval(expression):
return name
it is possible to a limited extent. the answer is similar to the solution by #tamtam .
The given example assumes the following assumptions -
You are searching for a variable by its value
The variable has a distinct value
The value is in the global namespace
Example:
testVar = "unique value"
varNameAsString = [k for k,v in globals().items() if v == "unique value"]
#
# the variable "varNameAsString" will contain all the variable name that matches
# the value "unique value"
# for this example, it will be a list of a single entry "testVar"
#
print(varNameAsString)
Output : ['testVar']
You can extend this example for any other variable/data type
I'd like to point out a use case for this that is not an anti-pattern, and there is no better way to do it.
This seems to be a missing feature in python.
There are a number of functions, like patch.object, that take the name of a method or property to be patched or accessed.
Consider this:
patch.object(obj, "method_name", new_reg)
This can potentially start "false succeeding" when you change the name of a method. IE: you can ship a bug, you thought you were testing.... simply because of a bad method name refactor.
Now consider: varname. This could be an efficient, built-in function. But for now it can work by iterating an object or the caller's frame:
Now your call can be:
patch.member(obj, obj.method_name, new_reg)
And the patch function can call:
varname(var, obj=obj)
This would: assert that the var is bound to the obj and return the name of the member. Or if the obj is not specified, use the callers stack frame to derive it, etc.
Could be made an efficient built in at some point, but here's a definition that works. I deliberately didn't support builtins, easy to add tho:
Feel free to stick this in a package called varname.py, and use it in your patch.object calls:
patch.object(obj, varname(obj, obj.method_name), new_reg)
Note: this was written for python 3.
import inspect
def _varname_dict(var, dct):
key_name = None
for key, val in dct.items():
if val is var:
if key_name is not None:
raise NotImplementedError("Duplicate names not supported %s, %s" % (key_name, key))
key_name = key
return key_name
def _varname_obj(var, obj):
key_name = None
for key in dir(obj):
val = getattr(obj, key)
equal = val is var
if equal:
if key_name is not None:
raise NotImplementedError("Duplicate names not supported %s, %s" % (key_name, key))
key_name = key
return key_name
def varname(var, obj=None):
if obj is None:
if hasattr(var, "__self__"):
return var.__name__
caller_frame = inspect.currentframe().f_back
try:
ret = _varname_dict(var, caller_frame.f_locals)
except NameError:
ret = _varname_dict(var, caller_frame.f_globals)
else:
ret = _varname_obj(var, obj)
if ret is None:
raise NameError("Name not found. (Note: builtins not supported)")
return ret
This will work for simnple data types (str, int, float, list etc.)
>>> def my_print(var_str) :
print var_str+':', globals()[var_str]
>>> a = 5
>>> b = ['hello', ',world!']
>>> my_print('a')
a: 5
>>> my_print('b')
b: ['hello', ',world!']
It's not very Pythonesque but I was curious and found this solution. You need to duplicate the globals dictionary since its size will change as soon as you define a new variable.
def var_to_name(var):
# noinspection PyTypeChecker
dict_vars = dict(globals().items())
var_string = None
for name in dict_vars.keys():
if dict_vars[name] is var:
var_string = name
break
return var_string
if __name__ == "__main__":
test = 3
print(f"test = {test}")
print(f"variable name: {var_to_name(test)}")
which returns:
test = 3
variable name: test
To get the variable name of var as a string:
var = 1000
var_name = [k for k,v in locals().items() if v == var][0]
print(var_name) # ---> outputs 'var'
Thanks #restrepo, this was exactly what I needed to create a standard save_df_to_file() function. For this, I made some small changes to your tostr() function. Hope this will help someone else:
def variabletostr(**df):
variablename = list(df.keys())[0]
return variablename
variabletostr(df=0)
The original question is pretty old, but I found an almost solution with Python 3. (I say almost because I think you can get close to a solution but I do not believe there is a solution concrete enough to satisfy the exact request).
First, you might want to consider the following:
objects are a core concept in Python, and they may be assigned a variable, but the variable itself is a bound name (think pointer or reference) not the object itself
var is just a variable name bound to an object and that object could have more than one reference (in your example it does not seem to)
in this case, var appears to be in the global namespace so you can use the global builtin conveniently named global
different name references to the same object will all share the same id which can be checked by running the id builtin id like so: id(var)
This function grabs the global variables and filters out the ones matching the content of your variable.
def get_bound_names(target_variable):
'''Returns a list of bound object names.'''
return [k for k, v in globals().items() if v is target_variable]
The real challenge here is that you are not guaranteed to get back the variable name by itself. It will be a list, but that list will contain the variable name you are looking for. If your target variable (bound to an object) is really the only bound name, you could access it this way:
bound_names = get_variable_names(target_variable)
var_string = bound_names[0]
Possible for Python >= 3.8 (with f'{var=}' string )
Not sure if this could be used in production code, but in Python 3.8(and up) you can use f' string debugging specifier. Add = at the end of an expression, and it will print both the expression and its value:
my_salary_variable = 5000
print(f'{my_salary_variable = }')
Output:
my_salary_variable = 5000
To uncover this magic here is another example:
param_list = f'{my_salary_variable=}'.split('=')
print(param_list)
Output:
['my_salary_variable', '5000']
Explanation: when you put '=' after your var in f'string, it returns a string with variable name, '=' and its value. Split it with .split('=') and get a List of 2 strings, [0] - your_variable_name, and [1] - actual object of variable.
Pick up [0] element of the list if you need variable name only.
my_salary_variable = 5000
param_list = f'{my_salary_variable=}'.split('=')
print(param_list[0])
Output:
my_salary_variable
or, in one line
my_salary_variable = 5000
print(f'{my_salary_variable=}'.split('=')[0])
Output:
my_salary_variable
Works with functions too:
def my_super_calc_foo(number):
return number**3
print(f'{my_super_calc_foo(5) = }')
print(f'{my_super_calc_foo(5)=}'.split('='))
Output:
my_super_calc_foo(5) = 125
['my_super_calc_foo(5)', '125']
Process finished with exit code 0
This module works for converting variables names to a string:
https://pypi.org/project/varname/
Use it like this:
from varname import nameof
variable=0
name=nameof(variable)
print(name)
//output: variable
Install it by:
pip install varname
print "var"
print "something_else"
Or did you mean something_else?

How do I check if a variable exists?

I want to check if a variable exists. Now I'm doing something like this:
try:
myVar
except NameError:
# Do something.
Are there other ways without exceptions?
To check the existence of a local variable:
if 'myVar' in locals():
# myVar exists.
To check the existence of a global variable:
if 'myVar' in globals():
# myVar exists.
To check if an object has an attribute:
if hasattr(obj, 'attr_name'):
# obj.attr_name exists.
The use of variables that have yet to been defined or set (implicitly or explicitly) is often a bad thing in any language, since it tends to indicate that the logic of the program hasn't been thought through properly, and is likely to result in unpredictable behaviour.
If you need to do it in Python, the following trick, which is similar to yours, will ensure that a variable has some value before use:
try:
myVar
except NameError:
myVar = None # or some other default value.
# Now you're free to use myVar without Python complaining.
However, I'm still not convinced that's a good idea - in my opinion, you should try to refactor your code so that this situation does not occur.
By way of an example, the following code was given below in a comment, to allow line drawing from a previous point to the current point:
if last:
draw(last, current);
last = current
In the case where last has not been bound to a value, that won't help in Python at all since even the checking of last will raise an exception. A better idea would be to ensure last does have a value, one that can be used to decide whether or not it is valid. That would be something like:
last = None
# some time passes ...
if last is not None:
draw(last, current);
last = current
That ensures the variable exists and that you only use it if it's valid for what you need it for. This is what I assume the if last was meant to do in the comment code (but didn't), and you can still add the code to force this if you have no control over the initial setting of the variable, using the exception method above:
# Variable 'last' may or may not be bound to a value at this point.
try:
last
except NameError:
last = None
# It will always now be bound to a value at this point.
if last is not None:
draw(last, current);
last = current
A simple way is to initialize it at first saying myVar = None
Then later on:
if myVar is not None:
# Do something
Using try/except is the best way to test for a variable's existence. But there's almost certainly a better way of doing whatever it is you're doing than setting/testing global variables.
For example, if you want to initialize a module-level variable the first time you call some function, you're better off with code something like this:
my_variable = None
def InitMyVariable():
global my_variable
if my_variable is None:
my_variable = ...
for objects/modules, you can also
'var' in dir(obj)
For example,
>>> class Something(object):
... pass
...
>>> c = Something()
>>> c.a = 1
>>> 'a' in dir(c)
True
>>> 'b' in dir(c)
False
I will assume that the test is going to be used in a function, similar to user97370's answer. I don't like that answer because it pollutes the global namespace. One way to fix it is to use a class instead:
class InitMyVariable(object):
my_variable = None
def __call__(self):
if self.my_variable is None:
self.my_variable = ...
I don't like this, because it complicates the code and opens up questions such as, should this confirm to the Singleton programming pattern? Fortunately, Python has allowed functions to have attributes for a while, which gives us this simple solution:
def InitMyVariable():
if InitMyVariable.my_variable is None:
InitMyVariable.my_variable = ...
InitMyVariable.my_variable = None
catch is called except in Python. other than that it's fine for such simple cases. There's the AttributeError that can be used to check if an object has an attribute.
A way that often works well for handling this kind of situation is to not explicitly check if the variable exists but just go ahead and wrap the first usage of the possibly non-existing variable in a try/except NameError:
# Search for entry.
for x in y:
if x == 3:
found = x
# Work with found entry.
try:
print('Found: {0}'.format(found))
except NameError:
print('Not found')
else:
# Handle rest of Found case here
...
I created a custom function.
def exists(var):
return var in globals()
Then the call the function like follows replacing variable_name with the variable you want to check:
exists("variable_name")
Will return True or False
Like so:
def no(var):
"give var as a string (quote it like 'var')"
assert(var not in vars())
assert(var not in globals())
assert(var not in vars(__builtins__))
import keyword
assert(var not in keyword.kwlist)
Then later:
no('foo')
foo = ....
If your new variable foo is not safe to use, you'll get an AssertionError exception which will point to the line that failed, and then you will know better.
Here is the obvious contrived self-reference:
no('no')
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-88-d14ecc6b025a> in <module>
----> 1 no('no')
<ipython-input-86-888a9df72be0> in no(var)
2 "give var as a string (quote it)"
3 assert( var not in vars())
----> 4 assert( var not in globals())
5 assert( var not in vars(__builtins__))
6 import keyword
AssertionError:
It may not be performant, but you generalise the solution to a function that checks both local variables and global variables.
import inspect
def exists_var(var_name):
frame = inspect.currentframe()
try:
return var_name in frame.f_back.f_locals or var_name in globals()
finally:
del frame
Then you can use it like this:
exists_var('myVar')
Short variant:
my_var = some_value if 'my_var' not in globals() else my_var:
This was my scenario:
for i in generate_numbers():
do_something(i)
# Use the last i.
I can’t easily determine the length of the iterable, and that means that i may or may not exist depending on whether the iterable produces an empty sequence.
If I want to use the last i of the iterable (an i that doesn’t exist for an empty sequence) I can do one of two things:
i = None # Declare the variable.
for i in generate_numbers():
do_something(i)
use_last(i)
or
for i in generate_numbers():
do_something(i)
try:
use_last(i)
except UnboundLocalError:
pass # i didn’t exist because sequence was empty.
The first solution may be problematic because I can’t tell (depending on the sequence values) whether i was the last element. The second solution is more accurate in that respect.
Also a possibility for objects, use __dict__.
class A(object):
def __init__(self):
self.m = 1
a = A()
assert "m" in a.__dict__
assert "k" not in a.__dict__

Categories

Resources