Python - Difference between variable value declaration on Fibonacci function - python

I'm kind of beginner in python. I was looking at one the types to make a fibonacci function,
def fib(n):
a=0
b=1
while a<n:
print a
a,b=b,a+b
and I saw the a,b=b,a+b declaration. So, I thought a=b and b=a+b were the same to a,b=a,b+a, so I changed the function for it to be like this:
def fib(n):
a=0
b=1
while a<n:
print a
a=b
b=a+b
and I thought it would be right, but when I executed the program, I got a different output. Can someone explain to me the difference between those two types of declaration?
Thanks, anyway.

b, a+b creates a tuple containing those two values. Then a, b = ... unpacks the tuple and assigns its values to the variables. In your code however you overwrite the value of a first, so the second line uses the new value.
a, b = b, a + b
is roughly equal to:
tmp = a
a = b
b = tmp + b

When Python executes
a,b = b, a+b
it evaluates the right-hand side first, then unpacks the tuple and assigns the values to a and b. Notice that a+b on the right-hand side is using the old values for a.
When Python executes
a=b
b=a+b
it evaluates b and assigns its value to a.
Then it evaluates a+b and assigns that value to b. Notice now that a+b is using the new value for a.

That syntax simultaneously assigns new values to a and b based on the current values. The reason it's not equivalent is that when you write the two separate statements, the second assignment uses the new value of a instead of the old value of a.

In the first example, a isn't updated to take the value of b until the entire line has been evaluated -- so b is actually a + b.
In you example, you've already set a to b, so the last line (b=a+b) could just as easily be b=b+b.
It's all in the order in which things are evaluated.

Related

difference between these two fibonacci python code

What is the difference between these two python code?.i thought both are same but the output i am getting is different
def fibonacci(num):
a=1
b=1
series=[]
series.append(a)
series.append(b)
for i in range(1,num-1):
series.append(a+b)
#a,b=b,a+b
a=b
b=a+b
return series
print(fibonacci(10))
def fibonacci(num):
a=1
b=1
series=[]
series.append(a)
series.append(b)
for i in range(1,num-1):
series.append(a+b)
a,b=b,a+b
#a=b
#b=a+b
return series
print(fibonacci(10))
In the first method
a=b
b=a+b
is an incorrect way of swapping, when you say a=b you have lost the value of a, so b=a+b is the same as b=b+b, which is not what you want.
Another way to achieve an equivalent result to this approach, a,b = b,a+b, is by using a temporary variable to store a, as follows:
tmp = a
a = b
b = tmp + b
The issue here is about storing the values you are calculating, on the first snippet you are saying a+b only on the second snippet you are saying b =a+b. The value of b is changing when you say b = a+b.
Hope my explanation is understandable.You are re-assigning the value of b o the first snippet (b=a+b)

Inline change input arguement by a function, not by using class method

Try to define a function to inline update input arguments, but doesn't find the way to go.
For example,
def swap(a, b):
# Result here not return to arguments after called
a, b = b, a
a, b = 5, 3
swap(a, b) # Expect a=3, b=5 after call swap
My question is how to define the function, not different way to call swap or class method. Python does not support call by reference, maybe no way for it.
Integers are immutable objects.
Thus, when you pass them into the function, all that gets changed are the local references. There is nothing you can do to make the function alter the values of the main-program variables a and b.
The way to return a variable from a function is by calling return. For example,
def swap(a, b):
a, b = b, a
return a, b
a, b = swap(b, a)
This seems entirely pointless, though. For something like this, it would be better to just do it outside the function.
a, b = 5, 3
a, b = b, a
If you really needed to change the variables inside a function, and you knew what they were referred to outside the function, you could use the global keyword.
a, b = 5, 3
def swap(): # No parameters necessary.
global a
global b
a, b = b, a
swap()

Why are only mutable variables accessible in nested functions?

here is a simple (useless) function:
def f(x):
b = [x]
def g(a):
b[0] -= 1
return a - b[0]
return g
it works fine. let's change it a tiny bit:
def f(x):
b = x
def g(a):
b -= 1
return a - b
return g
Now it gives an error saying that b is undefined! Sure, it can be solved using nonlocal, but I'd like to know why does this happen in the first place? Why are mutables accessable and immutables aren't?
Technically, it has nothing to do with mutable or immutable (the language does not know whether a type is "mutable" or not). The difference here is because you are assigning to the variable in one case and just reading from it in the other case.
In your second example, the line b -= 1 is the same as b = b - 1. The fact you are assigning to the variable b makes a local variable named b, separate from the outside variable named b. Since the local variable b has not been assigned to when evaluating the right side of the assignment, reading from the local b there is an error.
In your first example, the line b[0] -= 1 is the same as b[0] = b[0] - 1. But that is not a variable assignment. That is just a list element access. It is just syntactic sugar for b.__setitem__(0, b.__getitem__(0) - 1). You are not assigning to the variable b here -- all you're doing is reading from the variable b two times (in order to call methods on the object it points to). Since you are only reading from b, it uses the external variable b.
If in the first example, with your mutable list, you did a variable assignment like you did in the second example, it would equally create a local variable, and the reading of that local variable before assignment would also not work:
def f(x):
b = [x]
def g(a):
b = [b[0] - 1]
return a - b[0]
return g

Use the result of the return of one function in another function [duplicate]

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 6 months ago.
I know there are several questions about this, I read but I could not understand. I'm trying to use the result of the return of one function in another:
def multiplication(a):
c = a*a
return c
def subtraction(c):
d = c - 2
return d
print(subtraction(c))
Output:
NameError: name 'c' is not defined
I know that there is a possibility of using global variables, but I have seen that this is not a good idea since the variables can change their value.
EDIT:
These two functions are just idiotic examples. I have two functions with words and I need to use the return of the first function in the second function. In case of this my idiotic example, I need the result of the first function (c) in the second function.
You are not calling your functions properly.
def multiplication(a):
c = a*a
return c
def subtraction(c):
d = c - 2
return d
# first store some value in a variable
a = 2
# then pass this variable to your multiplication function
# and store the return value
c = multiplication(a)
# then pass the returned value to your second function and print it
print(subtraction(c))
Does this makes things clearer?
def multiplication(a):
c = a*a
return c
def subtraction(c):
d = c - 2
return d
print(multiplication(5)) # 25
print(subtraction(5)) # 3
print(multiplication(subtraction(5))) # 9
print(subtraction(multiplication(5))) # 23
I think you're trying to do what's happing in the last print statement: first call the multiplication function, and then call the subtraction function on the result.
Note that the variable c in your multiplication function is an entirely different variable from the c in your subtraction function. So much so, that it may make things more clear to rename your variables, perhaps something like this:
def multiplication(a):
product = a * a
return product
def subtraction(a):
difference = a - 2
return difference
So why not use return value?
print(subtraction(multiplication(24)))
?
'c' is not declared outside the 'subtraction' function.
You need to give need to declare 'c' before printing.
Let's say you want 'c' to be 5, then:
c = 5
print(subtraction(c))
You have defined two functions which both return a number.
If you call subtraction(c) you will get the error you see, because there is no c.
If you define a c in scope of the print statmenet
c = 42
print(subtraction(c))
it will be ok.
Try thinking of it like this: each function takes a variable does things to it and returns a number.
e.g.
>>> multiplication(101)
10201
That this happened to be called c isnide the function isn't known outside the function (i.e scope).
You can save the number to a variable
>>> x = multiplication(101)
Then x remembers that value.
Or
>>> c = multiplication(101)
This is not the same c as you have inside the functions.
(And after the question edit):
Decide what value you want to call the first function with, for example 101:
>>> c = multiplication(101)
then use that return to call the next function:
>>>> subtraction(c)
Or just chain them togther:
subtraction( multiplication(101) )
To start the chain you will need to use a string, int or defined variable.
Otherwise you get name not defined errors.
Once a variable is used in a function it goes out of scope when the function ends.

What is happening in this Python program?

I'd like to know what is getting assigned to what in line 8.
# Iterators
class Fibs:
def __init__(self):
self.a = 0
self.b = 1
def next(self):
self.a, self.b = self.b, self.a+self.b # <--- here
return self.a
def __iter__(self):
return self
fibs = Fibs()
for f in fibs:
if f > 1000:
print f
break
The rest of the program I really don't need much explanation. I'm not sure what's getting assigned to what.
It's a multiple assignment roughly equivalent to this:
tmp = self.a
self.a = self.b
self.b = tmp + self.b
Or this pseudo-code:
a' = b
b' = a + b
As you can see the multiple assignment is much more concise than separate assignments and more closely resembles the pseudo-code example.
Almost that example is given in the Python documentation as an example of calculating Fibonacci numbers. One of the advantages of the multiple assignment is that the variables on the right hand side are evaluated before any of the assignments take place, saving the need for the temporary variable in this case.
It's a pair assignment, a shorthand of
t = self.a
self.a = self.b
self.b = t+self.b
just to use an one-liner instead that two assignments.. to be precise i think that the left operand of the assignment is considered a tuple of two elements, so you are like assigning to tuple (self.a, self,b) the value (self.b, self.a+self.b) which does the same thing as the three separate assignments written before without the need of a temporary variable. This because, while without using tuple the assignments are executed sequentially, in your example they are resolved at the same time, preserving the value of self.a in second assignment.
As stated in documentation:
Assignment of an object to a target list is recursively defined as follows.
If the target list is a single target: The object is assigned to that target.
If the target list is a comma-separated list of targets (your case): The object must be an iterable with the same number of items as there are targets in the target list, and the items are assigned, from left to right, to the corresponding targets. (This rule is relaxed as of Python 1.5; in earlier versions, the object had to be a tuple. Since strings are sequences, an assignment like a, b = "xy" is now legal as long as the string has the right length.)
Without looking at the surrounding code, I'd say it's the heart of an algorithm for computing Fibonacci numbers.
It translates to the equivalent of:
a = b
b = a + b
...thereby computing the next number(s) in the sequence.
If you look at a sequence of numbers like
1 1 2 3 5 8 13 21 ...
and you let a and b be the last two numbers, then afterwards you'll have the next number in b and the former last number (b) in a.
The reason to use that strange notation is so as to accomplish both assignments at the same time. If they were done sequentially as in the 2 lines above, the value of a would be clobbered in the first line and you'd just be doubling b in the 2nd line.
Be aware that a paired assignment is not a "special feature" of Python. If you know a bit about Python, it's something you already know about but you may not know you know. When you put the following into the python console:
>>> 'a', 'b'
What you get in return is:
('a', 'b')
In other words, a tuple. In your example,
self.a, self.b = self.b, self.a+self.b
what you're really doing is:
(self.a, self.b) = (self.b, self.a+self.b)
Create a tuple that contains the value of self.b and the value of self.a+self.b. (The tuple on the right.)
Create a tuple that contains self.a and self.b. (The left-hand tuple.)
In order to create that left-hand tuple, create a new instance of self.a and self.b for that new tuple. Their old values don't matter anymore: they're in the temporary right-hand tuple.
Assign value 0 of the left tuple variable to value 0 of the right tuple.
Assign value 1 of the left tuple variable to value 1 of the right tuple.
Now that both variables of the left tuple are assigned, delete both tuples. The new variables remain with their new values.
So, for example, you can do:
>>> a, b = 1, 2
>>> a, b
(1, 2)
>>> a, b = b, a
>>> a, b
(2, 1)
There are still temporary variables involved under the hood, but you, the programmer, don't have to deal with them.

Categories