This question already has answers here:
How do I get a result (output) from a function? How can I use the result later?
(4 answers)
Closed 3 years ago.
I've been having some problems with the return statement and I can't seem to figure out what's wrong. It seemed to work fine yesterday, but today no function that contains it seems to work properly. Here's an example of what's going on:
def fpol(x):
y=x**4
return(y)
If I then type in
fpol(4)
I'm given the answer 256 (as I would expect). If I then type in
print(y)
or try to use/view y in any way, I'm told
NameError: name 'y' is not defined
I've also tried it with return(y) being replaced by return y . I can also insert print(y) into the original function and that works fine, so I know that during the function, y actually does have a value, it's just not being returned. Any help is much appreciated.
Edit: I've now been able to work past the issue I had with the return function. Thanks to everyone who responded.
y is known only in the scope of the function fpol. You should assign the result to a variable, and only then print its value:
y = fpol(4)
print(y)
Note that y is a different variable here, it has nothing to do with the y inside the function. You could write:
x = fpol(4)
print(x)
I suspect you are trying to print(y) outside the function. The variable y is local in scope, that is only defined within fpol(). So you can print it there. You can do:,
def fpol(x):
y=x**4
return(y)
y = fpol(4)
print(y)
But not:
def fpol(x):
y=x**4
return(y)
print(y)
The variable y is only visible from within the function you have declared. To print the result of fpol(4) you can assign the returned value to a new variable:
returnedValue = fpol(4)
print(returnedValue)
I guess you need to store the value returned by the function in a variable and then print it:
y = fpol(4)
print y
y is out of scope. It was only in scope for your function call, and since the function fpol has ran and ended, the scope has died with it. We need to assign a variable that's visible to the print command. Let's reuse y for simplicity.
y = fpol(4)
print(y)
The key rule of thumb for python is every time you indent you have started a new scope! You must make sure your variables are in scope to use them.
y is a variable with scope that's local to function fpol().
it is not defined outside of that scope.
The code return y does not make y visible outside of the function in which it has been defined. It only returns the value of y to the caller as a function return value.
Using your example, the following would show you the value of y
def fpol(x):
y=x**4
print(y) # This will print the value of y
return(y)
print fpol(4) # This will print the returned result
But trying to print y after your function call will fail with the not defined error as the variable is defined only inside you function, i.e. it is local to that function. This is often referred to as the scope of a variable.
As soon as the function returns, y ceases to exist.
y is not defined outside th function
you can not do print(y)
probably you want
y = fpol(4)
print(y)
is not very good programming style, but you also can make y global variable. then it will be available after function, but pls do not do it.
finally you can do just
return y
no need ()
Related
This question already has answers here:
UnboundLocalError trying to use a variable (supposed to be global) that is (re)assigned (even after first use)
(14 answers)
Short description of the scoping rules?
(9 answers)
Closed 6 months ago.
If I run the following code:
x = 1
class Incr:
print(x)
x = x + 1
print(x)
print(x)
It prints:
1
2
1
Okay no problems, that's exactly what I expected. And if I do the following:
x = 1
class Incr:
global x
print(x)
x = x + 1
print(x)
print(x)
It prints:
1
2
2
Also what I expected. No problems there.
Now if I start making an increment function as follows:
x = 1
def incr():
print(x)
incr()
It prints 1 just as I expected. I assume it does this because it cannot find x in its local scope, so it searches its enclosing scope and finds x there. So far no problems.
Now if I do:
x = 1
def incr():
print(x)
x = x + 1
incr()
This gives me the following error in the traceback:
UnboundLocalError: local variable 'x' referenced before assignment.
Why does Python not just search the enclosing space for x when it cannot find a value of x to use for the assignment like my class Incr did? Note that I am not asking how to make this function work. I know the function will work if I do the following:
x = 1
def incr():
global x
print(x)
x = x + 1
print(x)
incr()
This will correctly print:
1
2
just as I expect. All I am asking is why it doesn't just pull x from the enclosing scope when the keyword global is not present just like it did for my class above. Why does the interpreter feel the need to report this as an UnboundLocalError when clearly it knows that some x exists. Since the function was able to read the value at x for printing, I know that it has x as part of its enclosing scope...so why does this not work just like the class example?
Why is using the value of x for print so different from using its value for assignment? I just don't get it.
Classes and functions are different, variables inside a class are actually assigned to the class's namespace as its attributes, while inside a function the variables are just normal variables that cannot be accessed outside of it.
The local variables inside a function are actually decided when the function gets parsed for the first time, and python will not search for them in global scope because it knows that you declared it as a local variable.
So, as soon as python sees a x = x + 1(assignment) and there's no global declared for that variable then python will not look for that variable in global or other scopes.
>>> x = 'outer'
>>> def func():
... x = 'inner' #x is a local variable now
... print x
...
>>> func()
inner
Common gotcha:
>>> x = 'outer'
>>> def func():
... print x #this won't access the global `x`
... x = 'inner' #`x` is a local variable
... print x
...
>>> func()
...
UnboundLocalError: local variable 'x' referenced before assignment
But when you use a global statement then python for look for that variable in global scope.
Read: Why am I getting an UnboundLocalError when the variable has a value?
nonlocal: For nested functions you can use the nonlocal statement in py3.x to modify a variable declared in an enclosing function.
But classes work differently, a variable x declared inside a class A actually becomes A.x:
>>> x = 'outer'
>>> class A:
... x += 'inside' #use the value of global `x` to create a new attribute `A.x`
... print x #prints `A.x`
...
outerinside
>>> print x
outer
You can also access the class attributes directly from global scope as well:
>>> A.x
'outerinside'
Using global in class:
>>> x = 'outer'
>>> class A:
... global x
... x += 'inner' #now x is not a class attribute, you just modified the global x
... print x
...
outerinner
>>> x
'outerinner'
>>> A.x
AttributeError: class A has no attribute 'x'
Function's gotcha will not raise an error in classes:
>>> x = 'outer'
>>> class A:
... print x #fetch from globals or builitns
... x = 'I am a class attribute' #declare a class attribute
... print x #print class attribute, i.e `A.x`
...
outer
I am a class attribute
>>> x
'outer'
>>> A.x
'I am a class attribute'
LEGB rule: if no global and nonlocal is used then python searches in this order.
>>> outer = 'global'
>>> def func():
enclosing = 'enclosing'
def inner():
inner = 'inner'
print inner #fetch from (L)ocal scope
print enclosing #fetch from (E)nclosing scope
print outer #fetch from (G)lobal scope
print any #fetch from (B)uilt-ins
inner()
...
>>> func()
inner
enclosing
global
<built-in function any>
From Python scopes and namespaces:
It is important to realize that scopes are determined textually: the global scope of a function defined in a module is that module’s namespace, no matter from where or by what alias the function is called. On the other hand, the actual search for names is done dynamically, at run time — however, the language definition is evolving towards static name resolution, at “compile” time, so don’t rely on dynamic name resolution! (In fact, local variables are already determined statically.)
Which means that, the scope for x = x + 1 is determined statically, before the function is called. And since this is an assignment, then 'x' becomes a local variable, and not looked up globally.
That is also the reason why from mod import * is disallowed in functions. Because the interpreter won't import modules for you in compile time to know the names you are using in the function. i.e, it must know all names referenced in the function at compile time.
It's the rule Python follows - get used to it ;-) There is a practical reason: both the compiler and human readers can determine which variables are local by looking only at the function. Which names are local has nothing to do with the context in which a function appears, and it's generally a Very Good Idea to follow rules that limit the amount of source code you have to stare at to answer a question.
About:
I assume it does this because it cannot find x in its local scope, so
it searches its enclosing scope and finds x.
Not quite: the compiler determines at compile time which names are and aren't local. There's no dynamic "hmm - is this local or global?" search going on at runtime. The precise rules are spelled out here.
As to why you don't need to declare a name global just to reference its value, I like Fredrik Lundh's old answer here. In practice, it is indeed valuable that a global statement alerts code readers to that a function may be rebinding a global name.
Because that's the way it was designed to work.
Basically, if you have an assignment anywhere in your function, then that variable becomes local to that function (unless you've used global, of course).
Because it would lead to very hard to track down bugs!
When you type that x = x + 1, you could have meant to increment an x in the enclosing scope... or you could have simply forgotten that you already used x somewhere else and been trying to declare a local variable.
I would prefer the interpreter to only allow you to change the parent namespace if you intend to- this way you can't do it by accident.
I can try and make an educated guess why it works this way.
When Python encounters a string x = x + 1 in your function, it has to decide where to look up the x.
It could say "the first occurrence of x is global, and the second one is local", but this is quite ambiguous (and therefore against Python philosophy). This could be made part of the syntax, but it potentially leads to tricky bugs. Therefore it was decided to be consistent about it, and treat all occurrences as either global or local variables.
There is an assignment, therefore if x was supposed to be global, there would be a global statement, but none is found.
Therefore, x is local, but it is not bound to anything, and yet it is used in the expression x + 1. Throw UnboundLocalError.
As an extra example to the newly created A.x created within the class. The reassigning of x to 'inner' within the class does not update the global value of x because it is now a class variable.
x = 'outer'
class A:
x = x
print(x)
x = 'inner'
print(x)
print(x)
print(A.x)
This question already has answers here:
What are the differences between swap in C++ and Python?
(4 answers)
Closed 7 years ago.
I think the output should be x = 5, y = 3. But, when I tried executing it in jes it shows that x=3 and y=5.
My swap function is as follows:
def swap (x,y):
temp=x
x=y
y=temp
And from my driver function I call swap():
def driver():
x=3
y=5
swap(x,y)
print x
print y
I want to know why isn't the output as expected?
Well this is not a big issue in python you can return multiple values like try this snippet it might help you.
def swap(a,b):
return (b,a)
def driver(x,y):
print "Previous x=",x,"y=",y
x,y = swap(x,y)
print "Now x=", x, "y=",y
driver(3,5)
As other answers have suggested, this really doesn't require functions. Since you have decided to use them though, you might as well try and understand a bit more about scopes.
In order to retain the swapped values you need to return them or else they get lost after the execution of swap():
def swap (x,y):
temp=x
x=y
y=temp
return x, y # must return the swapped values.
Then, in the function where you call swap() you assign the returned values to the variables that you swapped:
def driver():
x=3
y=5
x, y = swap(x,y) # re-assign values
print x
print y
Running driver() now will give you the swapped value:
5
3
This happens because in the function swap() the variables x and y you pass as arguments are treated as local to that function, only swap can see their value. If you don't return this value back, it is lost and forgotten.
Integers are immutable in python. You are setting y to x and x to y in the local scope, but are not modifying the reference to the initial integers passed in. In python, the best you can do if you want to encapsulate a swap function that modifies in-place instead of by return is pass some kind of container object that is mutable and contain references to the thing you want to swap:
def swap(container):
container[0], container[1] = container[1], container[0]
And then call it like so:
x = 3
y = 5
container = [x,y]
swap(container)
FWIW, swap in python can be implemented in one line as simply as:
x, y = y, x
Which is probably syntactically clearer in most cases anyway.
See also Python passing an integer by reference
In python assignment changes the identity of an object rather than its value (unless you are mutating the content). This is worth noting that, as per Python Data Model
Every object has an identity, a type and a value.
So interchanging the identities inside swap would not change the identity inside the driver. Moreover, python does not allow you to change the value of an immutable types so, there is no other possible ways to swap the values inside the swap method.
def outside(x=1):
def printHam():
x = x+1
print x
return printHam
myfunc = outside(7)
myfunc()
This doesn't works gives error Local variable referenced before assignment error python
However this works
def outside(x=1):
def printHam():
print x + 1
return printHam
myfunc = outside(7)
myfunc()
Because you are assigning x in the first case, python will assume x is a local variable (which is the default). In the second case you aren't assigning it so it will check the global scope.
If you want this example to work, you have to pass the outer x into the inner function like so:
def outside(x=1):
def printHam(x=x):
x = x+1
print x
return printHam
That being said, this seems like a horribly contrived use case, so there's probably a better solution for your actual use case. But I can't tell you what it is without knowing more about what you're trying to do.
Can someone explain what's going on here
x = 10
def foo():
print "x in foo = ",x
if x: x = 8 -------------> mysterious line
foo()
print "x in main = ",x
In the above code, If i comment out the mysterious line (if x: x = 8)
I get the output
x in foo = 10
x in main = 10
Otherwise I end up with error
"UnboundLocalError: local variable 'x' referenced before assignment"
Why so?
I know global x is helpful only when I need to modify a global variable locally.
As soon as you make an assignment to x anywhere in the function, it becomes a local variable, even if there are references to its value prior to the assignment.
In your function, you assign to x with no global declaration, so x is a local variable. However, you attempt to read x in the function before it's assigned to, so you have an unbound local at that point.
What may seem strange at first is that local names are detected statically: if the name x is assigned anywhere in the function, Python assumes that x is a local name everywhere in the function.
In other words, the line order in your function is misleading: as long as x is assigned somewhere in the function, the first line's x becomes a reference to a local variable (which at this code point is still unbound).
Like Wooble already said, you need to declare the modifikation of a global variable before usage.
def foo():
global x
print "x in foo = ",x
if x: x = 8
x = 8 anywhere in the function without global x makes it a local variable. print x fails because a local variable is not initialized
I started working in Python just recently and haven't fully learned all the nuts and bolts of it, but recently I came across this post that explains why python has closures, in there, there is a sample code that goes like this:
y = 0
def foo():
x = [0]
def bar():
print x[0], y
def change(z):
global y
x[0] = y = z
change(1)
bar()
change(2)
bar()
change(3)
bar()
change(4)
bar()
foo()
1 1
2 2
3 3
and basically I don't understand how it actually works, and what construct like x[0] does in this case, or actually I understand what it's doing, I just don't get how is it this :)
Before the nonlocal keyword was added in Python 3 (and still today, if you're stuck on 2.* for whatever reason), a nested function just couldn't rebind a local barename of its outer function -- because, normally, an assignment statement to a barename, such as x = 23, means that x is a local name for the function containing that statement. global exists (and has existed for a long time) to allow assignments to bind or rebind module-level barenames -- but nothing (except for nonlocal in Python 3, as I said) to allow assignments to bind or rebind names in the outer function.
The solution is of course very simple: since you cannot bind or rebind such a barename, use instead a name that is not bare -- an indexing or an attribute of some object named in the outer function. Of course, said object must be of a type that lets you rebind an indexing (e.g., a list), or one that lets you bind or rebind an attribute (e.g., a function), and a list is normally the simplest and most direct approach for this. x is exactly that list in this code sample -- it exists only in order to let nested function change rebind x[0].
It might be simpler to understand if you look at this simplified code where I have removed the global variable:
def foo():
x = [0]
def bar():
print x[0]
def change(z):
x[0] = z
change(1)
bar()
foo()
The first line in foo creates a list with one element. Then bar is defined to be a function which prints the first element in x and the function change modifies the first element of the list. When change(1) is called the value of x becomes [1].
This code is trying to explain when python creates a new variable, and when python reuses an existing variable. I rewrote the above code slightly to make the point more clear.
y = "lion"
def foo():
x = ["tiger"]
w = "bear"
def bar():
print y, x[0], w
def change(z):
global y
x[0] = z
y = z
w = z
bar()
change("zap")
bar()
foo()
This will produce this output:
lion tiger bear
zap zap bear
The point is that the inner function change is able to affect the variable y, and the elements of array x, but it does not change w (because it gets its own local variable w that is not shared).
x = [0] creates a new list with the value 0 in it. x[0] references the zero-eth element in the list, which also happens to be zero.
The example is referencing closures, or passable blocks of code within code.