About variable scope? - python

I had a math test today and one of the extra credit questions on the test was
product = 1
for i in range(1,7,2):
print i
product = product * i
print i
print product
We were supposed to list out the steps of the loop which was easy; but it got me thinking, why does this program run? the second print i seems out of place to me. I would think that the i only exists for the for loop and then get's destroyed so when you call the second print i there is no variable i and you get an error.
Why does i remain a global variable?

The Devil is in the Details
Naming and binding
A block is a piece of Python program text that is executed as a unit.
The following are blocks: a module, a function body, and a class
definition.
Or in simple words, a for loop is not a block
A scope defines the visibility of a name within a block. If a local
variable is defined in a block, its scope includes that block. If the
definition occurs in a function block, the scope extends to any blocks
contained within the defining one, unless a contained block introduces
a different binding for the name.
So any variable defined is visible from the point of definition to the end of scope of the block, function, module or class definition.
Why does i remain a global variable?
From the nomenclature parlance, I will call i a global variable, if your highlighted code is part of the module rather than a defined function.

Python does not have block scope. Any variables defined in a function are visible from that point only, until the end of the function.

Related

When does a closure in Python finish execution or go out of scope?

I am trying to wrap my brain around closures. I’ve been looking at a lot of sources, but this question is based mainly on the explanation in Wikipedia.
I think I get the idea of a callback as a closure, to handle events that happen after something in the outer function has happened / been called. I guess that’s what happening with deferreds in Scrapy.
I’ve also seen examples in Python using the logging module.
Ok, but, but, you can’t call a closure on its own, right? Because that would be calling it outside the scope of where it was defined. Putting it another way, you can’t call a closure directly, you have to call the enclosing function which returns it. But if that’s the case, then the use case for closures is limited by its dependency on the outer function. The fact that it remembers the free variables of the enclosing environment after the outer function has ceased execution does not make the closure a little portable unit you can take and use anywhere and it will work without the outer function, right?
But if that’s right, then how can this also be right:
“...When the closure is entered at a later time, possibly with a
different lexical environment, the function is executed with its
non-local variables referring to the ones captured by the closure, not
the current environment…” Wikipedia - same link - #(“Implementation and theory”)
This is why I am struggling so hard with closures. The idea that they remember values post execution sounds, at least to me, like it has a life independent of the enclosing function, as though you can call it or use it in “a different lexical environment”. But that’s not true if the enclosing function is right there with it, is it?
This example from datacamp helps spell out what I find confusing in a simpler example:
In Python, a function is also considered a object, which means that it
can be returned and assigned to a variable. In the next example,
you'll see that instead of inner() being called inside outer(), return
inner is used. Then, outer() is called with a string argument and
assigned to closure. Now, even though the functions inner() and
outer() have finished executing, their message is still preserved. By
calling closure(), the message can be printed.
def outer(message):
# enclosing function
def inner():
# nested function
print(message)
return inner
closure = outer("Hello world!")
closure()
Hello world!
Notice that if you call closure without parentheses, only the type of
the object will be returned. You can see that it's of the type function
__main__.outer.<locals>.inner.closure
<function __main__.outer.<locals>.inner>
Now, even though the functions inner() and outer() have finished
executing, their message is still preserved.
In what sense have either inner() or outer() “finished executing” in this example? They haven’t even been called until you call closure()!
What am I missing here? Thanks.
They haven’t even been called until you call closure()!
Actually, the statement closure = outer("Hello world!") calls the outer() function with the argument "Hello world!". At that time, the outer() function executes, thereby defining the inner() function and returning the function inner itself, assigning the function to the variable closure. At this point, outer() has "finished executing".
Next, by calling closure(), the function inner() is actually invoked, returning the preserved message.
The description is poorly worded; the function inner wasn't executed during the call to outer, just the def statement that defines it.
Among other attributes, the function object defined by def inner(): ... has one named _closure__ that contains the value to use when the nonlocal name message is looked up.
>>> closure.__closure__[0].cell_contents
'Hello'
To the best of my understanding (which is not, admittedly, great), each nonlocal variable in the definition of inner is numbered, and a tuple containing one cell object per nonlocal name is stored in __closure__. Each cell has an attribute cell_contents which contains the value held by the nonlocal name when outer returns.

How to bind a name with multiple objects or values in python

I saw in a book about language description that says
On the other hand, a name can be bound to no object (a dangling pointer),
one object (the usual case), or several objects (a parameter name in a
recursive function).
How can we bind a name to several objects? Isnt that what we call an array for example where all elements have the same name but with index? For a recursive function like the example here:
x = 0
def f(y):
global x
x += 1
if x < 4 :
y +=100
f(y)
else: return
f(100)
Is the name y binded with multiple values that are created recursively since the nametable has already the y name binded to an initial value which is being reproduced with recursion?
EDITED Just press here Visualizer and see what it generates. :)
No.
A name is bound to one single object . When we are talking about Python - it is either bound to a single object in a given context, or do not exist at all.
What happens, is that the inner workings may have the name defined in several "layers" - but your code will only see one of those.
If a name is a variable in a recursive function, you will only see whatver is bound to it in the current running context - each time there is a function call in Python, the execution frame, which is an object which holds several attributes of the running code, including a reference to the local variables, is frozen. On the called function, a new execuciton frame is created, and there, the variable names are bound again to whatever new values they have in the called context. Your code just "see" this instance.
Then, there is the issue of global variables and builtin objects in Python: if a name is not a local variable in the function execution context, it is searched in the globals variables for the module (again, just one of those will be visible).ANd if the name is not defiend in the globals, them, Python looks for it in globals().__builtins__ that is your last call.
If I understand you correctly, you're asking about what rules Python has for creating variables in different scopes. Python uses lexical scoping on the function level.
It's hard to tell exactly what you're getting at with the code you've written, but, while there may be a different value associated with y in different scopes (with a value of y defined at each level of recursion), your code will only ever be able to see one at a time (the value defined at the scope in which you're operating).
To really understand scoping rules in Python, I would have a look at PEP 227. Also, have a look at this Stack Overflow question.
Finally, to be able to speak intelligently about what a "name" is in Python, I suggest you read about how Python is a "Call-By-Object" language.
At this point, we are capable of understanding that, instead of a "nametable", python uses a dictionary to hold what is accessible in a given scope. See this answer for a little more detail. The implication of this is that you can never have two of the same name in a single scope (for the same reason you can't have two of the same key in a python dictionary). So, while y may exist in a dictionary for a different scope, you have no way of accessing it, since you can only access the variables in the current scope's dictionary.
The key is:
several objects (a parameter name in a recursive function).
The passage is almost certainly not referring to arrays, but simply to the fact that in a recursive function (or any function, but a recursive function is likely to have multiple activations at one time), a parameter may be bound to a different value in each recursive call.
This does not mean that you can access each such object in every stack frame; indeed the point of the technique is to ensure that only one such value is accessible in each stack frame.
Firstly, you should mention in the question that the sentence from the book is not related explicitly to Python (as jsbueno wrote, one name is bound to exactly one object in Python).
Anyway, name bound to no object is a bit inaccurate. Generally, names are related to variables, and name related to a dangling pointer is the name of that pointer variable.
When speaking about the variable scope (i.e. the part of code where the variable is used), one variable name can be used only for a single value at a time. However, there may be other parts of code, independent on the one where we think about that variable. In the other part of code, the same name can be used; however, the two variables with the same name are totally isolated. This is the case of local variables also in the case of function bodies. If the language allows recursion, it must be capable to create another isolated space of local variable even for another call of the same function.
In Python, each function can also access outer variables, but it is more usual to use the inner, local variables. Whenever you assign a name some value, it is created in the local space.

Where is nonlocals()?

How do I obtain the non-local variables for the current scope? The functions vars, locals, and globals exist, but is there a function to get the nonlocals?
Why aren't the nonlocals listed when calling vars?
Update
My issue is that there's no way to enumerate the variables available in the current scope, as neither vars or globals includes the non-locals AFAICT.
I frequently use vars in code such as the following:
'{meh[0]}/{meh[3]} {a}{b}{c}'.format(**vars())
Which fails if any of these variables are in the scope of a containing function.
From within running code, you can easily get the names of the nonlocal variables - but retriving their content in a way a call to locals gets you a dictionary is a bit trickier.
The used nonlocal variable names are stored in the current running code object, in the co_freevars attribute.
So, getting the nonlocal names is a matter of:
names = inspect.currentframe().f_code.co_freevars
The contents for these variables, however, are stored in the __closure__ attribute (func_closure, in Python 2), of the function object instead. (Not the code object). The problem is that, without "aid from outside", there is no easy way for a running code to get to the function object it is running on. You can get to the frame object, which links to the code object, but there are no links back to the function object. (For a top level defined function one could explicitly use the function known name, as used in the def statement` but for an enclosed function, that is returned to a caller, there is no way of knowing its name either).
So, one has to resort to a trick - getting all the objects that link to the current code object, by using the gc module (garbage collector) - there is a gc.get_referrers call - it will return all the function objects that link to the code object one holds.
So, inside a function with non_local variables one could do:
import inspect, gc
from types import FunctionType
def a(b):
b1 = 2
def c():
nonlocal b1
print (b)
code = inspect.currentframe().f_code
names = code.co_freevars
function = [func for func in gc.get_referrers(code) if isinstance(func, FunctionType)][0]
nonlocals = dict (zip(names, (x.cell_contents for x in function.__closure__ )))
print(nonlocals)
return inspect.currentframe()
return c
c = a(5)
f = c()
And therefore retrieve the names and values of the nonlocals. But this won't work if you have more than one instance of that function around (that is, if the function of interested was created more than once with more than one call to the functin that generates it) - becasue all of those instances will link to the same code object. The example above, assumes there is only one function running with the current code - and would work correctly in this case. Another call to the factrory function would create another function, with potentially other values for the nonlocal variables, but with the same code object - the function = list genrator above would retrieve all of those, and arbitrarily pick the first of those.
The "correct" function is the one on which the current code is executing - I am trying to think of a way of retrieving this information, but can't get to it. If I can, I will complete this answer, but for now, this can't help you to retrieve the nonlocals values values.
(just found out that trying to use "eval" with a nonlocal variable name won't work as well)
It looks like that the only thing linking the current running frame to the function object where the nonlocal variables values are held is created at run time inside the native side of the Python interpreter. I can't think of a way of getting to it short of using the ctypes module to look at interpreters data structures at runtime, which would, of course, be unsuitable for any actual production code.
The bottom line: you can reliably retrieve the nonlocal variable names. But it looks like you can't get their value given their name as a string (nor rebind then).
You could try opening a feature-request for a "nonlocals" call on Python's bug tracker or on Python-ideas mailing list.

Correctness about variable scope

I'm currently developing some things in Python and I have a question about variables scope.
This is the code:
a = None
anything = False
if anything:
a = 1
else:
a = 2
print a # prints 2
If I remove the first line (a = None) the code still works as before. However in this case I'd be declaring the variable inside an "if" block, and regarding other languages like Java, that variable would only be visible inside the "if".
How exactly variable scoping works in Python and what's the good way to program in cases like this?
Thanks!
As a rule of thumb, scopes are created in three places:
File-scope - otherwise known as module scope
Class-scope - created inside class blocks
Function-scope - created inside def blocks
(There are a few exceptions to these.)
Assigning to a name reserves it in the scope namespace, marked as unbound until reaching the first assignment. So for a mental model, you are assigning values to names in a scope.
I believe that Python uses function scope for local variables. That is, in any given function, if you assign a value to a local variable, it will be available from that moment onwards within that function until it returns. Therefore, since both branches of your code are guaranteed to assign to a, there is no need to assign None to a initially.
Note that when you can also access variables declared in outer functions -- in other words, Python has closures.
def adder(first):
def add(second):
return first + second
return add
This defines a function called adder. When called with an argument first, it will return a function that adds whatever argument it receives to first and return that value. For instance:
add_two = adder(2)
add_three = adder(3)
add_two(4) # = 6
add_three(4) # = 7
However, although you can read the value from the outer function, you can't change it (unlike in many other languages). For instance, imagine trying to implement an accumulator. You might write code like so:
def accumulator():
total = 0
def add(number):
total += number
return total
return add
Unfortunately, trying to use this code results in an error message:
UnboundLocalError: local variable 'total' referenced before assignment
This is because the line total += number tries to change the value of total, which cannot be done in this way in Python.
There is no problem assigning the variable in the if block.
In this case it is being assigned on both branches, so you can see it will definitely be defined when you come to print it.
If one of the branches did not assign to a then a NameError exception would be raise when you try to print it after that branch
Python doesn't need variables to be declared initially, so you can declare and define at arbitrary points. And yes, the scope is function scope, so it will be visible outside the if.
i'm quite a beginner programmer, but for what i know, in python private variables don't exist. see private variables in the python documentation for a detailed discussion.
useful informations can also be found in the section "scopes and namespaces" on the same page.
personally, i write code like the one you posted pretty much every day, especially when the condition relies in getting input from the user, for example
if len(sys.argv)==2:
f = open(sys.argv[1], 'r')
else:
print ('provide input file')
i do declare variables before using them for structured types, for example i declare an empty list before appending its items within a loop.
hope it helps.

A small question about python's variable scope

I am a beginner of python and have a question, very confusing for me.
If I define a function first but within the function I have to use a variable which is defined in another function below, can I do it like this? Or how can I import the return things of another function into a function?
for example:
def hello(x,y):
good=hi(iy,ix)
"then do somethings,and use the parameter'good'."
return something
def hi(iy,ix):
"code"
return good
The scope of functions hello and hi are entirely different. They do not have any variables in common.
Note that the result of calling hi(x,y) is some object. You save that object with the name good in the function hello.
The variable named good in hello is a different variable, unrelated to the variable named good in the function hi.
They're spelled the same, but the exist in different namespaces. To prove this, change the spelling the good variable in one of the two functions, you'll see that things still work.
Edit. Follow-up: "so what should i do if i want use the result of hi function in hello function?"
Nothing unusual. Look at hello closely.
def hello(x,y):
fordf150 = hi(y,x)
"then do somethings,and use the variable 'fordf150'."
return something
def hi( ix, iy ):
"compute some value, good."
return good
Some script evaluates hello( 2, 3).
Python creates a new namespace for the evaluation of hello.
In hello, x is bound to the object 2. Binding is done position order.
In hello, y is bound to the object 3.
In hello, Python evaluates the first statement, fordf150 = hi( y, x ), y is 3, x is 2.
a. Python creates a new namespace for the evaluation of hi.
b. In hi, ix is bound to the object 3. Binding is done position order.
c. In hi, iy is bound to the object 2.
d. In hi, something happens and good is bound to some object, say 3.1415926.
e. In hi, a return is executed; identifying an object as the value for hi. In this case, the object is named by good and is the object 3.1415926.
f. The hi namespace is discarded. good, ix and iy vanish. The object (3.1415926), however, remains as the value of evaluating hi.
In hello, Python finishes the first statement, fordf150 = hi( y, x ), y is 3, x is 2. The value of hi is 3.1415926.
a. fordf150 is bound to the object created by evaluating hi, 3.1415926.
In hello, Python moves on to other statements.
At some point something is bound to an object, say, 2.718281828459045.
In hello, a return is executed; identifying an object as the value for hello. In this case, the object is named by something and is the object 2.718281828459045.
The namespace is discarded. fordf150 and something vanish, as do x and y. The object (2.718281828459045), however, remains as the value of evaluating hello.
Whatever program or script called hello gets the answer.
If you want to define a variable to the global namespace from inside a function, and thereby make it accessible by other functions in this space, you can use the global keyword. Here's some examples
varA = 5 #A normal declaration of an integer in the main "global" namespace
def funcA():
print varA #This works, because the variable was defined in the global namespace
#and functions have read access to this.
def changeA():
varA = 2 #This however, defines a variable in the function's own namespace
#Because of this, it's not accessible by other functions.
#It has also replaced the global variable, though only inside this function
def newVar():
global varB #By using the global keyword, you assign this variable to the global namespace
varB = 5
def funcB():
print varB #Making it accessible to other functions
Conclusion: variables defined in a function stays in the function's namespace. It still has access to the global namespace for reading only, unless the variable has been called with the global keyword.
The term global isn't entirely global as it may seem at first. It's practically only a link to the lowest namespace in the file you're working in. Global keywords cannot be accessed in another module.
As a mild warning, this may be considered to be less "good practice" by some.
your example program works, because the two instances of 'good' are different variables (you just happen to have both variables with the same name). The following code is exactly the same:
def hello(x,y):
good=hi(iy,ix)
"then do somethings,and use the parameter'good'."
return something
def hi(iy,ix):
"code"
return great
More details on the python scoping rules are here :
Short Description of Python Scoping Rules
The "hello" function doesn't mind you calling the "hi" function which is hasn't been defined yet, provided you don't try to actually use the "hello" function until after the both functions have been defined.

Categories

Resources