My functions in Python aren't returning values that I expect them to. Here is a MWE:
a = 6
b = 18
c = 0
def random_function(c):
c = b/a
return c
random_function(c)
print(c)
I expect this function to print 3, but instead it prints 0. I have just updated from 2.7 to 3.6 and this would have worked in 2.7 - what am I doing wrong?
Need to store returned value from method.
a = 6
b = 18
c = 0
def random_function(c):
c = b/a
return c
c= random_function(c)
print(c)
As #Dharmesh said, you need to store the value of c when it comes out of random_function().
i.e. c = random_function(c)
The Reason:
Scope is everything. When you change the value of c from within the function, it only affects the value of c within the scope of that function and doesn't change its value in the global context.
In order for the value you assigned to c from within the function to be preserved, you need to assign c the value returned by the function.
you are printing c value which was assigned globally.
a = 6
b = 18
c = 0
def random_function(c):
c = b/a
return c # -- this variable scope is local
random_function(c)
print(c) #-- prints Global variable
to print as you expected, you need to change your function call like below
print (random_function(c))
or
c = random_function(c) # this will re assign global value of 'c' with function return value
print(c)
Related
My code is as follows...
def addition(a, b):
c = a + b
return c
And I then want to be able to use C later on in the program as a variable. For example...
d = c * 3
However, I get a NameError that 'C' is not defined... But I have returned c, so why can I not use it later on in the code?! So confused. Thanks!
(This is obviously a simpler version of what I want to do but thought I'd keep it simple so I can understand the basics of why I cannot call on this variable outside my function even though I am returning the variable. Thanks)
You have returned the value of c but not the whole variable i.e. the name c exists only within the scope it is instantiated.
So, if you want to use the value returned, you should re-assign it to a new name. You can do it by re-assigning it to c again, but it could be any name you wanted.
def addition(a, b):
c = a + b
return c
new_var = addition(1,2) #new_var gets the value 3
c = addition(2,3) #c gets the value 5
Take a look at this nice explanation about variables and scopes (link)
You usually define a function to use it later in your code. For that case, use another global variable c:
def addition(a, b):
c = a + b
return c
c = addition(1, 2)
d = c * 3 # d == 9
Functions allow this usage of repeated code, or procedure distinction, so that you can later write in your code
m = addition(4, 5)
and it will store the required result of the functionality into m.
If you want to define c in the function and use it later, you can use global variables.
c = 0
def addition(a, b):
global c
c = a + b
return c
It's not considered good to use globals, though. You could also call the function in the variable assignment.
d = addition(a, b) * 3
For this, you need to put real numbers in the place of a and b. I recommend you use the second option.
This works.
a = [2,5,3,7,9,12]
def mean_list(x):
b = 0
for i in x:
b=b+i
c = b/len(x)
return c
print(mean_list(a))
but this doesn't work, even though I have declared my list as global. Why?
def mean_list(x):
global a
a = [2,5,3,7,9,12]
b = 0
for i in x:
b=b+i
c = b/len(x)
return c
print(mean_list(a))
Your list (a) is only created when you call the function. So it is not created unless you call the function once, try calling the function with another variable and then a
This question already has answers here:
How to get/set local variables of a function (from outside) in Python? [duplicate]
(5 answers)
Closed 9 years ago.
Let us consider the following program
def fib(n):
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, a+b
c = result
print c
return result
f100 = fib(100)
print result
#print c
How can I access the variable 'c' from out side the function? Is it possible? I know
print result
will give the same, but i want to know is there any method to access 'c' outside the function?
You could declare c as global, although that's not generally a pattern you'd want to encourage. You'd do that like this:
c = None
def fib(n):
global c
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, a+b
c = result
return result
f100 = fib(100)
print result
print c
You could also restructure your function as a class with a __call__ method which would let you expose internal values as attributes, such as:
class fibber(object):
def __init__(self):
self.c = None
def __call__(self, n):
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, a+b
self.c = result
return result
fib = fibber()
f100 = fib(100)
print result
print fib.c
Local variables only exist in the context of the function they are defined in. That's what makes them local. So the whole variable c does not exist anymore once the function terminates and returns its result value.
You can of course save the value of that variable in a different one, e. g. a field of the function itself:
fib.c = c
Since the function itself will exist also after it terminated, so will its fields, and so will fib.c.
But I must stress that this is just a hack. Normally if you want to access a value outside of a function it is a good idea to make the variable holding that value not local.
You can declare c a global variable:
def fib(n):
global c
result = []
a, b = 0, 1
while b < n:
result.append(b)
a, b = b, a+b
c = result
print c
return result
result = fib(10)
print result
print c
This question already has answers here:
nonlocal keyword in Python 2.x
(10 answers)
Is it possible to modify a variable in python that is in an outer (enclosing), but not global, scope?
(9 answers)
Closed 8 years ago.
For the following Python 2.7 code:
#!/usr/bin/python
def func_a():
print "func_a"
c = 0
def func_b():
c += 3
print "func_b", c
def func_c():
print "func_c", c
print "c", c
func_b()
c += 2
func_c()
c += 2
func_b()
c += 2
func_c()
print "end"
func_a()
I get the following error:
File "./a.py", line 9, in func_b
c += 3
UnboundLocalError: local variable 'c' referenced before assignment
But when I comment out the line c += 3 in func_b, I get the following output:
func_a
c 0
func_b 0
func_c 2
func_b 4
func_c 6
end
Isn't c being accessed in both cases of += in func_b and = in func_c? Why doesn't it throw error for one but not for the other?
I don't have a choice of making c a global variable and then declaring global c in func_b. Anyway, the point is not to get c incremented in func_b but why it's throwing error for func_b and not for func_c while both are accessing a variable that's either local or global.
What you are seeing here is the difference between accessing and assigning variables. In Python 2.x you can only assign to variables in the innermost scope or the global scope (the latter is done by using the global statement). You can access variables in any enclosing scope, but you cannot access a variable in an enclosing scope and then assign to it in the innermost or global scope.
What this means is that if there is any assignment to a name inside of a function, that name must already be defined in the innermost scope before the name is accessed (unless the global statement was used). In your code the line c += 3 is essentially equivalent to the following:
tmp = c
c = tmp + 3
Because there is an assignment to c in the function, every other occurrence of c in that function will only look in the local scope for funcB. This is why you see the error, you are attempting to access c to get its current value for the +=, but in the local scope c has not been defined yet.
In Python 3 you could get around this issue by using the nonlocal statement, which allows you to assign to variables that are not in the current scope, but are also not in the global scope.
Your code would look something like this, with a similar line at the top of funcC:
def funcB():
nonlocal c
c += 3
...
In Python 2.x this isn't an option, and the only way you can change the value of a nonlocal variable is if it is mutable.
The simplest way to do this is to wrap your value in a list, and then modify and access the first element of that list in every place where you had previously just used the variable name:
def funcA():
print "funcA"
c = [0]
def funcB():
c[0] += 3
print "funcB", c[0]
def funcC():
c[0] = 5
print "funcC", c[0]
print "c", c[0]
funcB()
funcC()
funcB()
funcC()
print "end"
funcA()
...and the output:
funcA
c 0
funcB 3
funcC 5
funcB 8
funcC 5
end
Isn't 'c' being accessed in both cases of '+=' in funcB and '=' in funcC?
No, funcC makes a new variable, also called c. = is different in this respect from +=.
To get the behavior you (probably) want, wrap the variable up in a single-element list:
def outer():
c = [0]
def inner():
c[0] = 3
inner()
print c[0]
will print 3.
Edit: You'll want to pass c as an argument. Python 2 has no other way, AFAIK, to get the desired behavior. Python 3 introduces the nonlocal keyword for these cases.
1) Isn't c being accessed in both cases of += in funcB and = in funcC?
No, because c += 3 is the same as:
c = c + 3
^
|
and funcB does not know what this c is
2) I don't have a choice of making c a global variable and then declaring global c in funcB.
Please don't do that, just change:
def funcB():
with:
def funcB(c):
and call funcB(c) later in your code.
Note: You should also cosider to define funcB and funcC outside funcA
Another dirty workaround, which, however, doesn't require you to make c global. Everything the same, but:
def funcB():
globals()['c'] += 3
print "funcB", c
Try this:
def funcA():
print "funcA"
c = 0
def funcB(c):
c += 3
print "funcB", c
def funcC(c):
c = 5
print "funcC", c
print "c", c
funcB(c)
funcC(c)
funcB(c)
funcC(c)
print "end"
funcA()
And if you want to remember c value then:
def funcA():
print "funcA"
c = 0
def funcB(c):
c += 3
print "funcB", c
return c
def funcC(c):
c = 5
print "funcC", c
return c
print "c", c
c = funcB(c)
c = funcC(c)
c = funcB(c)
c = funcC(c)
print "end"
funcA()
that will produce:
funcA
c 0
funcB 3
funcC 5
funcB 8
funcC 5
end
C:\Python26\
Try this out:
A = 1
B = 2
C = A + B
def main():
global C
print A
The output of main() is 1.
Why is this? Why should main get to know about the other global variables used to evaluate C?
Global variables are always available to all local scopes in Python, including functions. In this case, within main() A, B, and C are all in scope.
The global keyword doesn't do what it seems you think it does; rather, it permits a local scope to manipulate a global function (it makes global variables "writable", so to speak). Consider these examples:
c = 4
print c
def foo():
c = 3
print c
foo()
print c
Here, the output will be
4
3
4
Now, consider this:
c = 4
print c
def foo():
global c
c = 3
print c
foo()
print c
In this case, the output will be
4
3
3
In the first case, c = 3 merely shadows c until its scope is up (i.e. when the function definition ends). In the second case, we're actually referring to a reference to a global c after we write global c, so changing the value of c will lead to a permanent change.
Functions can read variables in enclosing scopes. The global declaration is used to writing variables (to indiciate that they should be written to the global dictionary rather than the local dictionary).