Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm trying to understand function environments (global, local). Specifically, I get very confused when there is a nested function that has already been defined globally, for example:
def g(x):
print(x)
def f(f):
f(1)
f(g)
Can someone please help me with this concept? I would greatly appreciate it.
Thanks.
Python uses dictionaries to keep local and global variables in. When looking up a variable reference, it will look into the local dict first. If you want to reference a variable in the global dictionary, put the global keyword in front of it.
Also see answers to this question for more elaborate info.
I agree with user18044, however, is your confusion about the ’f(f)’? I agree that can be really confusing, especially in a non typed language. The argument to ’f’ is a function handle that has a local type scope with name ’f’. The way python decides which ’f’ gets used is explained by 18044. Python looks at the name ’f’ on the function definition and the local parameter ’f’ takes precidence over the global name ’f’ just like would be done if we had a global variable ’dude’ and a local variable ’dude’ in a function. The local overrides the global. Hopes this helps, and makes sense. :-)
The locals for a function consist of everything that was passed in, and every variable that is assigned to and not explicitly tagged as global (or nonlocal in 3.x).
The globals consist of everything that can be seen at global scope, including the function itself.
When a name is referenced, it is looked up in the locals first, and then in the globals if not found in the locals.
When the statement f(g) is run, the statement itself is at global scope, so there are no locals. f and g are both found in the globals: they are both functions. The function defined by def f... is called, with the function defined by def g... being passed as an argument.
When f(f) runs, f is in the locals for the function. It is bound to the passed-in value, which is the function defined by def g.... The body of the function has the statement f(1). 1 is a constant and no lookup is required. f is looked up in the locals, and the passed-in function is found. It - being the function known at global scope as g - is called.
Thus g is, likewise, run with the value 1 bound to the local variable x. That is forwarded to the function print (in 3.x; in 2.x, print is a keyword, so print x is a statement), which prints the value 1.
Related
This question already has answers here:
How to get local variables updated, when using the `exec` call?
(3 answers)
Closed 3 years ago.
I'm sure this has been asked and answered, but I couldn't find it specifically:
I'm just picking up Python and I'm not understanding a variable scope issue.
I've simplified the problem to the following:
Case 1:
def lev1():
exec("aaa=123")
print("lev1:",aaa)
lev1()
Case 2:
def lev1():
global aaa
exec("aaa=123")
print("lev1:",aaa)
lev1()
Case 3:
def lev1():
exec("global aaa ; aaa=123")
print("lev1:",aaa)
lev1()
Case 1 and Case 2 have aaa undefined in the print statement.
Case 3 works. Where does aaa actually exist in Case 1 and Case 2?
Is there a way to access aaa in Case 1 without a global declaration?
From the docs:
Note: The default locals act as described for function locals() below: modifications to the default locals dictionary should not be attempted. Pass an explicit locals dictionary if you need to see effects of the code on locals after function exec() returns.
In other words, if you call exec with one argument, you're not supposed to try to assign any variables, and Python doesn't promise what will happen if you try.
You can have the executed code assign to globals by passing globals() explicitly. (With an explicit globals dict and no explicit locals dict, exec will use the same dict for both globals and locals.)
def lev1():
exec("aaa=123", globals())
print("lev1:", aaa)
lev1()
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I am reading the book Python Programming for the Absolute Beginner by Mike Dawson and I was struck by a question that I had regarding functions.
Observing the code below
def func_1():
name = input('What is your name?')
def func_2():
print(name)
func_2()
I know that I cannot call the variable name in function 2 as it is local to function 1.
However, why can I call a function inside another function and then find the value of the user's input as such below?
def func_1():
name = input('What is your name?')
return name
def func_2():
user_input = func_1()
print(user_input)
func_2()
The important thing to consider here is the scope of the variable and/or function names you're using. Global scope means everything can see it, whether it's at the top level, inside a function, or even inside a method, which is inside a class.
Local scope means it's locked within the context of that block, and nothing outside of the block can see it. In your case, that block is a function.
(Note that this is a mild simplification and more complex rules exist around modules and includes, but this is a reasonable starter for 10...).
In your example above, the function has been defined at the global level, so its name, func_1 has global scope (you might also say that it is in the "global namespace". That means that anything can see it, including code inside other functions.
Conversely, the variable name has local scope, inside func_1, which means it is only visible inside func_1, and nowhere else.
When you return name, you're passing the value of name back to whatever called that function. That means that the user_input = func_1() receives the value that was returned and stores it in a new variable, called user_input.
The actual variable name is still only visible to func_1, but that value has been exposed to outside functions by returning it.
Edit: As requested by #Chris_Rands:
There is a function in Python that will give you a dictionary containing of all the global variables currently available in the program.
This is the globals() function. You can check something is at global scope by seeing if it is in this dictionary:
def func_1():
name = input('What is your name?')
def func_2():
print(name)
func_1_is_global = 'func_1' in globals() # value is 'True'
name_is_global = 'name' in globals() # value is 'False'
One additional edit for completeness: I state above that you're passing the value of name back. This is not strictly true as Python is pass-by-reference, but the waters get murky here and I didn't want to confuse the issue. More details here for the interested observer: How do I pass a variable by reference?
func_2 calls func1, which returns a value which you can print inside func_2. In your first example func_2 cannot see a local variable of function_1.
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.
This question already has answers here:
What's the scope of a variable initialized in an if statement?
(7 answers)
Closed 3 years ago.
In Python, are variable scopes inside if-statements visible outside of the if-statement? (coming from a Java background, so find this a bit odd)
In the following case, name is first defined inside the if-block but the variable is visible outside of the if-block as well. I was expecting an error to occur but 'joe' gets printed.
if 1==1:
name = 'joe'
print(name)
if statements don't define a scope in Python.
Neither do loops, with statements, try / except, etc.
Only modules, functions and classes define scopes.
See Python Scopes and Namespaces in the Python Tutorial.
Yes, in Python, variable scopes inside if-statements are visible outside of the if-statement.
Two related questions gave an interestion discussion:
Short Description of the Scoping Rules?
and
Python variable scope error
All python variables used in a function live in the function level scope. (ignoring global and closure variables)
It is useful in case like this:
if foo.contains('bar'):
value = 2 + foo.count('b')
else:
value = 0
That way I don't have to declare the variable before the if statement.
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.