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.
Related
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}')=}")
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.
This question already has answers here:
Keep the lifespan of variable after multiple function calls?
(4 answers)
Closed 5 years ago.
Assuming:
def myfunc(x):
listv = []
listv.append(x)
is there a keyword to stop a variable (listv) from being reassigned?
Let's suppose that NRA is a keyword:
def myfunc(x):
NRA listv = []
listv.append(x)
...line will be read and not reassigned but the variable still active appending new values for every function call. I know about the GLOBAL variable, but I just want to know is the keyword exists!
Variables in functions are not supposed to be persistent between function calls. Because functions are meant to be reusable codes that can be called from different context in the program. So to your answer, NO! There's no keyword for making a variable declared in function persistent.
This question already has answers here:
Does Python have class prototypes (or forward declarations)?
(6 answers)
Closed 8 years ago.
How do I prototype a method in a generic Python program similar to C++?
# Prototype
# Do Python prototyping
writeHello() # Gives an error as it was not defined yet
def writeHello():
print "Hello"
Python does not have prototyping because you do not need it.
Python looks up globals at runtime; this means that when you use writeHello the object is looked up there and then. The object does not need to exist at compile time, but does need to exist at runtime.
In C++ you need to prototype to allow two functions to depend on one another; the compiler then can work out that you are using the second, later-defined function. But because Python looks up the second function at runtime instead, no such forward definition is needed.
To illustrate with an example:
def foo(arg):
if not arg:
return bar()
def bar(arg=None):
if arg is not None:
return foo(arg)
Here, both foo and bar are looked up as globals when the functions are called, and you do not need a forward declaration of bar() for Python to compile foo() successfully.
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.