This question already has answers here:
Function not changing global variable
(4 answers)
Closed 5 years ago.
How does the code below give the output as None?
def funct(x):
x=7
x=11
x=test(x)
print(x)
Here is another code snippet:-
def func():
print (x)
x = 90
x = 1
func()
The output for this should be 90! The scope is searched as Local ,Enclosed , Global ,Build-in .Either x should here be searched as local or global
Please explain.
x here is not a global variable in the scope of the functions, as functions naturally create their own namespaces, which do not include any outer variables not passed in as a parameter.
There are many issues with your code, including the order of function calling, and the order of the operations inside the functions; but to answer your question in the broadest way possible, in order for you to access the x variable defined outside of your functions, in a greater scope that is, you need to reference its namespace, by prepending global x inside the body of each of your functions.
Read up on Python variables and scope, and recheck the other errors in your code I have stated above.
The first code snippet returns None for the simple fact that you didn't return any value from the function. You defined x as a local parameter, not a global variable. Since you didn't return any value, your call test(x) (which does not match the function name of funct), will become a value of None. This is clearly defined in the Python documentation. To get the local value back to your main program, try this:
test(x):
x = 7
return x
x = 11
x = test(x)
print(x)
Also, please note that your initial value of 11 is entirely ignored in the main program, and that your function ignores the value it's given. You should shorten this example to
func():
return 7
print(func())
Your second example will print the external value of 1 because you have not defined a local variable x at that point, and a function is allowed to reference global variables.
However, when you assign a value in the next, you create a local variable -- you have not declared x to be global, so you can't assign to the x in the main program.
Again, you do not return any value. Therefore, back in the main program, func() evaluates to None.
Does that clear up what happened?
Related
This question already has answers here:
Short description of the scoping rules?
(9 answers)
Closed 5 months ago.
I am confused about scope.
What, if anything, is the difference between assigning a variable 'within a function' and assigning one within an
indented block? I have read many places that if and try blocks do not create, or have, their own scope, but I have also
read that the scope of a variable is the innermost block where it is defined.
I googled but was not able to find an example of nonlocal inside an if or try block.
def sixdig2iso(pathfrom):
os.chdir(pathfrom)
filelist = os.listdir()
nonlocal xfrs
xfrs = 0
PyCharm says nonlocal variable 'xfrs' must be bound in an outer function scope
Isn't this the outermost part of this function? Then what's the problem?
Is the outermost part of this function != an outer function? Even if the scopes of each are different from the inner parts of those same functions?!
if xfrs == 0:
restofit = frs[1:]
try:
convert = datetime.strptime(mm, '%m%d%y')
except ValueError as e:
logger.info(f"For {filename}, mm is: {mm} - and the error is: {e}")
count_err += 1
ender = ' '.join(restofit)
fronter = str(convert.date())
PyCharm says the 2nd convert 'might' be used before assignment
I tried making an inner function
def sixdig2iso(pathfrom):
"""Converts six digit dates into proper datetime format in place."""
os.chdir(pathfrom)
filelist = os.listdir()
nonlocal xfrs
xfrs = 0
def blockscope():
But PyCharm gives me the same "nonlocal variable 'xfrs' must be bound in an outer function scope" warning.
UPDATE
My response is too long for a comment.
“We have to guess because you didn't provide a complete example”
I can never seem to get the balance between ‘not enough’ and ‘too much’ information for these questions. I probably didn’t think the part you say is missing was relevant, which goes to my understanding of the problem in the first place.
“ it doesn't matter how many nestings of function you create inside this function, nonlocal only looks outward.“
See, I didn’t know that. And I infer, then, it only looks ‘upward’, too, right?
“As .strptime() might fail with an exception, convert may end up not having been assigned a value, as you did not initialise convert outside the try block. “
Ok, good, that is very helpful. I didn’t realize (and PyCharm does not explain as you just did) this is what PyCharm was talking about. But this is also why I was confused about the ‘scope’ of a try block.
In the first example you give, xfrs is only defined in the function you've provided as an example. We have to guess because you didn't provide a complete example, but the message from PyCharm suggests that you did not define this function inside another function that already had such an identifier defined in it and there's no xfrs in the global scope either.
In the second example, you assign to convert in the try section of a try .. except block. As .strptime() might fail with an exception, convert may end up not having been assigned a value, as you did not initialise convert outside the try block. So, PyCharm is correct (again, we have to assume as you did not provide a complete example.
Finally, in the third example, you start defining a function inside the function, but still apply nonlocal to a variable in the sixdig2iso() scope - it doesn't matter how many nestings of function you create inside this function, nonlocal only looks outward.
A typical use of nonlocal is as #Carcigenicate provides in their link (some modifications here):
x = 0
def outer():
x = 1
def inner():
nonlocal x
x += 1
return x
return x, inner
v, f = outer()
print(x, v, f())
The function returned by outer() produces 2 when called, as its non-local variable x of inner() is the same as the local variable x of outer(), starting at 1 and having 1 added as the function is called.
You can tell that is what happens, as the value returned by outer() is 1, but calling the returned function f() returns 2. All the time, the global x is untouched.
Try changing nonlocal to global and you'll find the the result changes from:
0 1 2
To:
0 1 1
I hope that helps explain what is going on with nonlocal.
This question already has answers here:
How do I pass a variable by reference?
(39 answers)
How to get/set local variables of a function (from outside) in Python? [duplicate]
(5 answers)
Closed 3 years ago.
How do I assign a global variable to a function's return? The only way I seem to be able to get it to work properly is to assign the variable to the function itself. When I run the code, the variable assignment performs the function on that line, which is not what I want. I only want an assignment so I can use the variable later.
def random_function():
x = 3.14
return x
This is what I'd like to happen but does not work:
pi = x
This works but runs the function in the console on that line which is not something I want:
pi = random_function()
print(pi)
If you're inside a function but want to assign a new value to a global, you have to declare the global first. Otherwise the identifier will be assumed to be a local variable. What I mean is this:
pi = -1 # declare your global
def random_function():
global pi
x = 3.14
pi = x # now works, after the `global` line above
return x
If I understand it right, you want to assign the return value of your function to a variable?
x = random_function()
I think that's how you can write it. You can use whatever variable you want.
You've answered your question already. To assign a global variable to a function's return value, simply assign the variable to the function's call;
def random_function():
x = 3.14
return x
pi = random_function()
You can print pi in the console if you want to see it's value. Not required.
The global keyword is used in a function to refer to a global variable within that function and modify it. However even if the global keyword is not used and if we just try to print the variable, python assumes it is the global variable that is being referred and simply prints that like so.
a = 2
def foo():
print(a)
foo()
the above code outputs 2. But the following code throws an error.
a = 2
def foo():
print(a)
a = 3
foo()
I get an UnboundLocalError saying local variable 'a' was referenced before assignment. Now since python is an interpreted language and execution happens one line at a time, shouldn't it first print the global value of a which is 2 (like in the first case) and then create a local variable with the same name ans assign it to 3. In the second case how does the interpreter know right at the print statement that I am referring to another variable 'a' in the next line? Why doesn't it behave in the same way as above?
PS: I do understand that using the global keyword can help me change the value of a from 2 to 3.
Python byte code is interpreted; Python source is first compiled to byte code.
Names are either local or global within a single scope, and that determination is made at compile time; you can't switch half way through a fuction. If there is any assignment to a in the function, it is local everywhere in the function unless you use global a.
a = 2
def foo():
global a
print(a)
a = 3
Without the global statement, print(a) refers to the local name a, even though it occurs before the actual assignment.
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.
x=5
def printx()
print x
x=10
running this gives unboundlocal error
but when my function is just print x i get no error..
Simply assigning a value to x in the function is making it a local variable, therefore shadowing the global x = 5 specified on the previous line. And on the line you're trying to print x, the local version of x hasn't been initialized yet. It is curious how doing something on a later line is influencing lines that come before it, but that's just how it works.
You don't need any special declaration to read a global variable, therefore it works without the assignment inside the function. However, if you'd rather assign 10 to the global x instead of making a new, local x, you'll have to specify global x inside the function.