inner function accessing outer function's variable [duplicate] - python

This question already has answers here:
Can you explain closures (as they relate to Python)?
(13 answers)
Closed 6 years ago.
Let's suppose to have this simple code:
def my_outer_function():
outer_var = 123
def my_inner_function():
return outer_var + 1
return my_inner_function
get_inner = my_outer_function()
get_inner()
I wonder there isn't any kind of runtime error. outer_var - the variable of the outer function - is available only when that function is running on, i.e. it vanishes when my_outer_function ends. But when I call get_inner(), my_outer_function() is already ended so I would have bet on a runtime error since my_inner_function couldn't find outer_var.
How do you explain all this?

the variable of the outer function is available only when that function is running on, i.e. it vanishes when my_outer_function ends.
That's not entirely true. The variable is available in my_outer_function's scope. my_inner_function has the scope of its own declarations and its parent's scope.
my_inner_function references a variable outside of its own scope, and so those references are bound to my_inner_function as a closure when its parent's scope is no longer available. To learn more about closures, see Can you explain closures (as they relate to Python)? (taken from Paul Rooney's comment)

Related

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.

Why are objects allowed to be used after a block? [duplicate]

This question already has answers here:
Short description of the scoping rules?
(9 answers)
Closed 5 years ago.
In this code, why do a and b not get destroyed at the ends of their respective blocks?
flag = True
if flag:
a = 1
for i in range(2):
b = 2
print(a, b)
Instead, this code prints 1 2. Why does Python allow this? When can I rely on this behavior?
Read up on the scoping rules for Python. In short, a scope is started with a new module: function, method, class, etc. Mere control flow statements (e.g. if and for) do not start a new scope. The scope of a variable is from its firs definition to the end of that scope.
Since this example has only one scope, each variable is good from its first assignment to the end of the file.
Is that enough to clear up the problem?

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.

When does my function will go to previous scopes to look for a variable? [duplicate]

This question already has answers here:
UnboundLocalError trying to use a variable (supposed to be global) that is (re)assigned (even after first use)
(14 answers)
Is it possible to modify a variable in python that is in an outer (enclosing), but not global, scope?
(9 answers)
Closed 6 months ago.
in python 3.0 from what i know when i'm using variables that aren't found in the local scope it will go all the way back until it reaches the global scope to look for that variable.
I have this function:
def make_withdraw(balance):
def withdraw(amount):
if amount>balance:
return 'insuffiscient funds'
balance=balance-amount
return balance
return withdraw
p=make_withdraw(100)
print(p(30))
When i insert a line:
nonlocal balance
under the withdraw function definition it works well,
but when i don't it will give me an error that i reference local variable 'balance' before assignment, even if i have it in the make_withdraw function scope or in the global scope.
Why in other cases it will find a variable in previous scopes and in this one it won't?
Thanks!
There are too many questions on this topic. You should search before you ask.
Basically, since you have balance=balance-amount in function withdraw, Python thinks balance is defined inside this function, but when code runs to if amount>balance: line, it haven't seen balance's definition/assignment, so it complains local variable 'balance' before assignment.
nonlocal lets you assign values to a variable in an outer (but non-global) scope, it tells python balance is not defined in function withdraw but outside it.

Why 4 is returned for the follow code in Python [duplicate]

This question already has answers here:
Short description of the scoping rules?
(9 answers)
Closed 8 years ago.
>>> a = 10
>>> def f(x):
return x + a
>>> a = 3
>>> f(1)
According to my experience on Java, the definition of f contains a local variable a, but how could the global binding a been visible on the function f call stack environment?
I did a research on the python syntax and found that's true, could anybody offer some background on why python dealing variable scope this way? thanks.
Your function call is in the last line.
When the function gets called, python first looks up for local variables with name a,
if not found, it goes into global scope, and in global scope, the last assigned value of a is 3 ( just before the function was called)
What you may find even stranger is that this will also work:
>>> def f(x):
return x + a
>>> a = 3
>>> f(1)
Note that a hasn't even been defined before the function f. It still works because your call to f is after a is defined and placed in the global namespace. At that point, since f does not have a in its local namespace, it will fetch it from the global namespace.
You can fetch the contents of the global namespace and check for yourself with globals(), and the local namespace with locals(). There's also some neat tricks you can do by manipulating the namespaces directly, but that is in most cases considered bad coding practice in Python, unless you really have a compelling reason and know what you're doing.
It would return 4 because you declare a and f(x) a function then you give valuea=3 and then you give x=1 so the function would return 3+1 which is 4
Python decide variable scope in function based on where they have been assigned. As you didn't assigned variable 'a' inside function so it starts looking out and consider the global value.
In Python, variables that are only referenced inside a function are implicitly global. If a variable is assigned a new value anywhere within the function’s body, it’s assumed to be a local. If a variable is ever assigned a new value inside the function, the variable is implicitly local, and you need to explicitly declare it as global.
Ref : http://effbot.org/pyfaq/what-are-the-rules-for-local-and-global-variables-in-python.htm
Java is a purely object-oriented language, while Python is not. Python supports both structural as well as object-oriented paradigms.
Global variables are part of the structural programming paradigm. So global variables will be available in the scope of a function, unless another variable with exactly the same name exists in the local scope of that function.

Categories