Python: How to check if a variable has been already declared [duplicate] - python

This question already has answers here:
How do I check if a variable exists?
(14 answers)
Closed 9 years ago.
While working with many if/elif/else I sometime loose a track if a variable has been already declared. I would like to know a simple way to check if the variable foo has been already declared. What would be the simplest syntax to accomplish that?
P.s. It was interesting to see how globals() and locals() could be used to accomplish this.
EDIT:
I've ended up using:
if not 'myVariableName' in globals().keys(): myVariableName='someValue'
It's hard to track when and where/if app = QtGui.QApplication(sys.argv) had been already declared especially in situation when one gui module calls another and vise versa.
if 'app' in globals() (seems) helps to avoid an accidental variable re-declaration.

try:
foo
except NameError:
# does not exist
else:
# does exist

Rather than worrying about if a variable is declared, declare all variables from the start. You can give variables some value to indicate that it is still in a initial state, such as
foo = None
or, if you want to use None for some other purpose, you can create a unique value to indicate the initial state, such as
INITIAL = object()
foo = INITIAL
Later, if you need to check if the variable has been set, you could just use if:
if foo == INITIAL:
I think the main advantages to doing it this way are
You'll never accidentally raise a NameError.
There will be one place in your code where all the variables are
introduced, so readers of your code do not have to wonder what
variables are in play.
By the way, it is similarly a good idea to define all instance attributes in __init__, so there is no question about what attributes an instance may have.

Related

Using a list comprehension and string formatting on class properties [duplicate]

This question already has answers here:
How do I create variable variables?
(17 answers)
Closed 10 months ago.
Here is the basic class code:
class test:
for i in range(10):
exec(f'a{i}={i+1}')
My first attempt to create the list a_all was to do the following:
exec(f'a_all=[test.ak for k in range(0,10,2)]')
However, this doesn't work as exec does not 'unstring' ak the way I want it to. Other attempts failed because the exec function returns None. I'm not even confident anymore that exec could actually work.
Your non-listcomp code works as written (kinda surprised by that), defining attributes of test, so just use that if it's what you need (it's almost certainly a bad idea, but you do you).
This doesn't work in your listcomp code because:
test doesn't exist until the class definition completes (after you dedent at the end), so test.ANYTHING doesn't work inside the definition of test (you assign to top-level names, and they become attributes of test when the class finishes being defined, but they're just scoped names without test. qualification before then)
Omitting test doesn't work in Python 3 because listcomps have their own scope in Python 3; even if you fake it out to assign to each of your names in turn, the iteration variables don't leak to outer scope on Python 3.
In any event, what you're doing is nonsensical:
Your plain for loop code works, but
It's a bad idea; just have a single class attribute of the list and have users index it as needed. There's basically never a good reason to have a programmatically generated list of numbered variable names. That's reinventing lists, badly.
So just use:
class test:
a = range(0, 10, 2) # Or list(range(0, 10, 2)) if it must be mutable
and user's can do test.a[0], test.a[3], whatever they need.
You can use setattr and getattr to set class attributes.
class test:
def __init__(self):
for i in range(10):
setattr(self, f"a{i}", i + 1)
t = test()
for i in range(10):
print(f"{t.a1=} a{i}={getattr(t, f'a{i}')=}")

Python variable inheritance not working (as expected) [duplicate]

This question already has answers here:
How to create dynamical scoped variables in Python?
(4 answers)
Closed 2 years ago.
Why, in this code, can't I access db or file from inside do_more()?
def do_stuff(queue):
db = getDbConn()
while True:
file = queue.get() #DirEntry object
...
do_more(otherObject)
q.task_done()
I'm aware I could pass db and file as arguments to do_more(), but I feel like those variables should just be available in functions called from other functions. It works that way from main to first level functions. What am I missing here?
In the code you provided, you don't even attempt using the variables from do_stuff.
But as a general rule, you should be able to use variables from a parent function inside a child function, either by passing them as variables or by using them when initializing the child function, like this:
def foo():
foo2 = "foo"
def bar():
print(foo2)
bar()
foo()
If i did not answer your question let me know.
no , you cant access those variables , I know what you think , which is wrong.
you can access variables inside loops and if statements, not here.
imagine you have a function which is used in many different places, in that case you have access from this function to many variables which makes things complicated.
functions should be stand-alone objects which take some arguments do stuff and return something.so inside a function scope you can only see variables which are defined there and the arguments passed from the parent function using parenthesis.

locals() defined inside python function do not work [duplicate]

This question already has answers here:
Dynamically set local variable [duplicate]
(7 answers)
Any way to modify locals dictionary?
(5 answers)
Closed 2 years ago.
Consider below code:-
dct = {'one':[2,3]}
Now the below works,
for key,val in dct.items():
locals()[key] = val
print(one)
Result:
[2, 3]
But When I use function which I really want doesn't work. Please help
def ff(dct):
for key,val in dct.items():
locals()[key] = val
print(one)
ff(dct)
Result:
NameError: name 'one' is not defined
The result of the locals() call inside a function is not one that you can use to actually update locals using your method. The documentation makes that clear:
locals()
Update and return a dictionary representing the current local symbol table. Free variables are returned by locals() when it is called in function blocks, but not in class blocks. Note that at the module level, locals() and globals() are the same dictionary.
Note The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.
The reason why you cannot update locals using this method is that they are heavily optimised within the CPython source code(a). When you call locals(), it actually builds a dictionary (the "update and return" bit) based on these heavily optimised structures and that is what you get.
Writing a new key to that dictionary is not reflected back to the actual locals.
I believe the globals() return value does allow updates using this method because that's already a dictionary and it just gives you a reference to it, not a copy. That's why your code works outside of a function (see the clause above stating locals() and globals() are the same thing in that context).
From memory, Python 2 allowed you to do something like exec "answer = 42" and that would affect the locals. But, as with print, this was changed from a statement to a library call in Python 3, so the execution engine really has no idea what it does under the covers, meaning it cant magically bind locals with exec("answer = 42").
I suppose someone could request this as a feature since it would make dynamic programming a little easier. Whether it would get through the gauntlet, I have no idea, since the fact that you can provide your own locals dictionary to exec() means that you already have a way to detect variables that were bound by arbitrary code. They'll just be in a separate dictionary rather then in the actual locals area.
(a) Access to locals is via known indexes into the stack-frame local variable area, computed at compile time and embedded into the actual bypte code. Being able to add/change variables dynamically would break this optimisation.
This problem was raised as an issue back in early 2009 and the outcome was that it was too difficult without losing a lot of performance.

why the system says :NameError: name 'self' is not defined [duplicate]

This question already has answers here:
Python: How can I run eval() in the local scope of a function
(2 answers)
Closed 3 years ago.
My code is similar like this:
class NN(object):
def __init__(self,config=None,opts=None):
self.file_vars = ['self.corpusfile','self.dbfile']
self.corpusfile="data.json"
self.dbfile="db.json"
def saveNet(self):
for name in self.file_vars:
print(name)
print(eval(name))
b=dict( [(name,eval(name)) for name in self.file_vars])
a=NN()
a.saveNet()
the result is :
self.corpusfile
data.json
self.dbfile
db.json
error message is:
NameError: name 'self' is not defined
how to solve this problem?
The list comprehension has its own local variable scope. eval can't see self, because self comes from an outer scope, and nothing triggers the closure variable mechanism that would be necessary for eval to see the variable. (The self reference in self.file_vars doesn't trigger it, because that expression is evaluated outside the list comprehension's scope, despite being part of the list comprehension.)
Stop using eval. It's dangerous, almost always a bad idea, and completely unnecessary for something like this. Appropriate replacement tools might include getattr, self.__dict__, or something else, depending on what your full use case looks like.

Python: Variables are still accessible if defined in try or if? [duplicate]

This question already has answers here:
Short description of the scoping rules?
(9 answers)
Closed 5 months ago.
I'm a Python beginner and I am from C/C++ background. I'm using Python 2.7.
I read this article: A Beginner’s Guide to Python’s Namespaces, Scope Resolution, and the LEGB Rule, and I think I have some understanding of Python's these technologies.
Today I realized that I can write Python code like this:
if condition_1:
var_x = some_value
else:
var_x = another_value
print var_x
That is, var_x is still accessible even it is not define before the if. Because I am from C/C++ background, this is something new to me, as in C/C++, var_x are defined in the scope enclosed by if and else, therefore you cannot access it any more unless you define var_x before if.
I've tried to search the answers on Google but because I'm still new to Python, I don't even know where to start and what keywords I should use.
My guess is that, in Python, if does not create new scope. All the variables that are newly defined in if are just in the scope that if resides in and this is why the variable is still accessible after the if. However, if var_x, in the example above, is only defined in if but not in else, a warning will be issued to say that the print var_x may reference to a variable that may not be defined.
I have some confidence in my own understanding. However, could somebody help correct me if I'm wrong somewhere, or give me a link of the document that discusses about this??
Thanks.
My guess is that, in Python, if does not create new scope. All the variables that are newly defined in if are just in the scope that if resides in and this is why the variable is still accessible after the if.
That is correct. In Python, namespaces, that essentially decide about the variable scopes, are only created for modules, and functions (including methods; basically any def). So everything that happens within a function (and not in a sub-function) is placed in the same namespace.
It’s important to know however that the mere existance of an assignment within a function will reserve a name in the local namespace. This makes for some interesting situations:
def outer ():
x = 5
def inner ():
print(x)
# x = 10
inner()
outer()
In the code above, with that line commented out, the code will print 5 as you may expect. That’s because inner will look in the outer scope for the name x. If you add the line x = 10 though, the name x will be local to inner, so the earlier look up to x will look in the local namespace of inner. But since it hasn’t been assigned yet, you will receive an UnboundLocalError (“local variable 'x' referenced before assignment”). The nonlocal statement was added in Python 3 to overcome one issue from this: The situation where you want to actually modify the x of the outer scope within the inner function.
For more information on name lookup, see this related question.

Categories