I'm trying to write a simple code that uses a global variable. I'm getting the following error
UnboundLocalError: local variable 'x' referenced before assignment
global x
def update():
x = x + 1
x = 0
update()
print(x)
Your error occurred because in the function update, you are trying to edit a variable (x) that is not defined, at least not locally.
The global keyword should be inside the function, and hence tell that the x you are speaking about is the one defined outside of the function (therefore globally defined) :
def update():
global x
x = x + 1
x = 0
update()
print(x)
This would output 1, as expected.
You can take a look at this well detailed answer regarding the use of the global keyword.
Related
I have two async functions with local scope and one checking function with global scope. The two async functions reference each other (hence recursive behaviour).
All three functions are called from the main async function.
So the setup looks like this:
import asyncio
# globals
x = 0
async def main():
''' this is the main function '''
print('hello from main function')
print('local x:', x)
asyncio.ensure_future(what_is_x())
await first_async(x)
print('got here', x)
async def first_async(x):
''' this is a function '''
print('hello from first function')
x = x + 1
print('local x:', x)
await asyncio.sleep(2)
await second_async(x)
async def second_async(x):
print('hello from second function')
x = x + 1
print('local x:', x)
if x > 5:
print('exit second function...')
return
await asyncio.sleep(2)
await first_async(x)
async def what_is_x():
''' this is a function '''
while True:
print('what is x ?', x)
await asyncio.sleep(3)
if __name__ == "__main__":
syncio.run(main())
The result (of the above) is this:
hello from main function
local x: 0
hello from first function
local x: 1
what is x ? 0
hello from second function
local x: 2
what is x ? 0
hello from first function
local x: 3
what is x ? 0
hello from second function
local x: 4
hello from first function
local x: 5
what is x ? 0
hello from second function
local x: 6
exit second function...
got here 0
I try to avoid usage of the global keyword (supposedly best practice).
So my question is, what is the best way to ensure x is consistent throughout ?
And also, can i make what_is_x() block the other two async functions in the current setup ?
x in yours first_async and second_async functions is a normal, local variable, and changes in it are only withn the scope of each function. Each time a line with x = x + 1 is executed, the local variable changes its reference to a new int object.
THere is nothing "obscure" on this code. If you'd try to make x global in all three functions (by using the "global" statement, instead of passin g it as a parameter), it would be equaly easy to have code that would go into an infinite loop, and still have nothing of obscure going on.
The way it is, though, global x is never changed from its initial value.
If you really think you need everyone to sync using a global value, just do it - change your first_async and second_async functions to read:
async def first_async():
global x
...
instead. Also, there are context_vars that can handle the scope of variables per task, instead of globally: you'd also do not want to pass "x" as a parameter - but maybe it is more useful to whatever is your intent there - https://docs.python.org/3/library/contextvars.html
I'm working to complete a code challenge, where the goal is to create basic arithmetic from just functions. I'm working from a Python 3.8 Interpreter (EMACS Terminal)
Example, seven(times(five())) ---> should return 35
I am trying to code this solution utilizing global variable declarations, but for some reason, my variables are getting re-assigned in what seems to be out of order. I've included a code snippet below to show what I've done.
Here is a portion of what I have for my current solution:
left = 0
def five(x=None):
global left
if x == None:
return 5
else:
left = 5
print(f"Set Val:{left}")
return x
def seven(x=None):
global left
if x == None:
return 7
else:
left = 7
print(f"Set Val:{left}")
return x
def times(num):
global left
print(f"times val: {left}")
right = num
print(right)
return left*right
So I expect to receive 35, but instead, this returns 0, because python is executing the times() function before the global gets re-assigned. From what I can see in my code, I have written to reassign the left variable before calling return x, so why doesn't this work? Note that this is only reproducible in a terminal or similar python interpreter. Trying this in a notebook will most likely work as intended
I am learning the basic usage of python,and I'm confusing about how the variable runs in a practice question. Here are the code below:
x = 1
def change(a):
a = x + 1
print(x)
change(x)
x = 1
def change(a)
x = x + 1
print(x)
change(x)
This is how I think the process:
in the first code:change(x) means: x = x + 1 - print (x) - output:2
but in fact the result is 1.So the real process is: x(symbol in the function) = x(global variable) + 1, print(x), this x is the global variable.
is that right?
in the second code,I think still the output should be 2,but it shows me that UnboundLocalError: local variable 'x' referenced before assignment
so in the python,we can't use function to change the global variable?
Inside a function, you can read global variables but you cannot modify them without explicitly declaring them as global like this:
x = 1
def change(a):
global x # <- this is required since you're assigning a new value to x
x = x + 1
print(x)
change(x)
In the first case, with a = x + 1, the global declaration is not required since you're only reading the value of x, not modifying it. Also, the output is 1 in the first case, since you're printing x not a.
I am trying to call a variable from one function into another by using the command return, without success. This is the example code I have:
def G():
x = 2
y = 3
g = x*y
return g
def H():
r = 2*G(g)
print(r)
return r
H()
When I run the code i receive the following error NameError: name 'g' is not defined
Thanks in advance!
Your function def G(): returns a variable. Therefore, when you call it, you assign a new variable for the returned variable.
Therefore you could use the following code:
def H():
G = G()
r = 2*G
print (r)
You don't need to give this statement:
return r
While you've accepted the answer above, I'd like to take the time to help you learn and clean up your code.
NameError: name 'g' is not defined
You're getting this error because g is a local variable of the function G()
Clean Version:
def multiple_two_numbers():
"""
Multiplies two numbers
Args:
none
Returns:
product : the result of multiplying two numbers
"""
x = 2
y = 3
product = x*y
return product
def main():
result = multiple_two_numbers()
answer = 2 * result
print(answer)
if __name__ == "__main__":
# execute only if run as a script
main()
Problems with your code:
Have clear variable and method names. g and G can be quiet confusing to the reader.
Your not using the if __name__ == "__main__":
Your return in H() unnecessary as well as the H() function.
Use docstrings to help make your code more readable.
Questions from the comments:
I have one question what if I had two or more variables in the first
function but I only want to call one of them
Your function can have as many variables as you want. If you want to return more than one variable you can use a dictionary(key,value) List, or Tuple. It all depends on your requirements.
Is it necessary to give different names, a and b, to the new
variables or can I use the same x and g?
Absolutely! Declaring another variable called x or y will cause the previous declaration to be overwritten. This could make it hard to debug and you and readers of your code will be frustrated.
I have
def func1(var):
if var == 0:
return
else
var = var - 1
func1(var)
PROPOSAL = 1
def func2():
func1(PROPOSAL)
print(PROPOSAL)
In the recursive calls in func1, will the variable PROPOSAL be decremented, meaning the print statement will print 0?
Edit: I should've asked, why doesn't it do this?
No, the PROPOSAL global variable will not be decremented by your code. This isn't really because of scope, but because of how Python passes arguments.
When you call a function that takes an argument, the value of the argument you pass is bound to a parameter name, just like an assignment to a variable. If the value is mutable, an in-place modification through one name will be visible through the other name, but if the variable is immutable (as ints are in Python), you'll never see a change to one variable effect another.
Here's an example that shows functions and regular assignment working the same way:
x = 1
y = x # binds the y to the same value as x
y += 1 # modify y (which will rebind it, since integers are immutable)
print(x, y) # prints "1 2"
def func(z): # z is a local variable in func
z += 1
print(x, z)
func(x) # also prints "1 2", for exactly the same reasons as the code above
X = [1]
Y = X # again, binds Y to the same list as X
Y.append(2) # this time, we modify the list in place (without rebinding)
print(X, Y) # prints "[1, 2] [1, 2]", since both names still refer to the same list
def FUNC(Z):
Z.append(3):
print(X, Z)
FUNC(X) # prints "[1, 2, 3] [1, 2, 3]"
Of course, rebinding a variable that referred to a mutable value will also cause the change not to be reflected in other references to the original value. For instance, you replaced the append() calls in the second part of the code with Y = Y + [2] and Z = Z + [3], the original X list would not be changed, since those assignment statements rebind Y and Z rather than modifying the original values in place.
The "augmented assignment" operators like +=, -=, and *= are a bit tricky. They will first try to do an in-place modification if the value on the left side supports it (and many mutable types do). If the value doesn't support in-place modification of that kind (for instance, because it's an immutable object, or because the specific operator is not allowed), it will fall back on using the regular + operator to create a new value instead (if that fails too it will raise an exception).
func1(PROPOSAL) will return NONE and it won't affect the global PROPOSAL variable because you don't assign that return value to PROPOSAL.
func2() just calls func1() and then prints the PROPOSAL variable that wasn't changed it that scope just in func1(PROPOSAL)