Why One Liner Result Is Different - python

While working with Fibonacci sequence:
a = 1
b = 3
a, b = b, a + b
print a, b
This properly results to a = 3 and b = 4
Now if I would re-code it as:
a = 1
b = 3
a = b
b = a + b
print a, b
the resulting variable b is 6 instead of 4.
What happens "behind of scenes" when one-liner a, b = b, a + b is used?

This is a combination of tuple packing and sequence unpacking. It is parsed the same way as
(a, b) = (b, a + b)
The tuple on the right side is evaluated before the assignment, which is why the "old" values are used.

You said
b = 3
and then
a = b
and then
b = a + b
which is the same as
b = b + b
or, in other words,
b = 3 + 3,
so b = 6.
The first one is like a, b = 3, 1 + 3 or a, b = 3, 4 so b = 4.

( ) don't make the sequence a tuple, rather ,s do.
a, b = b, a + b # => (a,b) = (a, a+b) if written with brackets
So, it's standard tuple unpacking. But the thing with names a and b on the lest is they are names of different objects now, namely those known as b and result of a+b previously. This behavior is partly due to the fact that variable names in python are names, not boxes,like in C, that store values.

Related

Plus or minus an array by an array and store in a dictionary

I have done a ton of preprocessing and math on this data to arrive at two equally sized 3xN numpy arrays. A and B.
A = integers that have been classified as labels to predict B.
B = time series data.
I also have C which is just B[1:]
A and B are equal at their respective time steps and I can't figure out a better way to make a list of the next time step of B, so I have A[0:-1], B[0:-1] and C[1:])
I know that A + or - B is always == to at least 1 integer in C.
Example:
if A = [2,3,4] and B = [5,2,1] I know that at least 1 of C will be a 7,8,1,3, or any other combination of those numbers + or - each other.
How can I make a simple function to do this operation and check if it IS == to C and then store it as a key in a dictionary? The goal would be to create a neural network once this is complete to evaluate new data.
Just to give an example, if I understand what you are looking for:
a = [2,3,4]
b = [5,2,1]
c = set(b[1:])
sums = set([ aa + bb for aa in a for bb in b ])
subs1 = [ (aa - bb) for aa in a for bb in b if (aa - bb) > 0]
subs2 = [ bb - aa for bb in b for aa in a if (bb - aa) > 0]
subs = set(subs1 + subs2)
print(sums)
print(subs)
print(c)
print(len(sums & c)) #=> 0 c does not contains any of sums
print(len(subs & c)) #=> 2 c contains two of subs

Odd behavior in Fibonacci series in python 3?

This does not print the correct Fibonacci series i.e. 1 1 2 3 5 8...
print ('Fibonacci series...')
a,b = 0,1
while b<50:
print(b)
a = b
b = a + b
Please let me know if there is a better way to do this.
Firstly, there is an indentation error in the first code snippet. The last two lines should be indented so they are executed within the while loop.
print ('Fibonacci series...')
a,b = 0,1
while b<50:
print(b)
a = b
b = a+b
However, this still won't produce the correct result. Let's look at why these two code snippets are different.
a, b = b, a + b: This will assign a to b and b to a + b, with the evaluation of the right-hand side before the left-hand side. This means before looking at what variables to assign new values to, Python will first see what b and a + b are. This means the old value of a will be used for setting b = a + b. You can read more about this here.
a = 1
b = 2
a, b = b, a + b # set a to 2, set b to 1 + 2
print(a) # 2
print(b) # 3
a = b; b = a + b: This does assignment sequentially, such that a is first set to b, then used in the assignment calculation.
a = 1
b = 2
a = b # set a to 2
b = a + b # set b to 2 + 2
print(a) # 2
print(b) # 4
a=b
b = a+b
in the first code sample is equivalent to b = b * 2. Instead you want b += original_value(a). So you either need to do tuple assignment, as in the second code sample (a,b = b, a+b), or use a temp variable:
temp = a
a = b
b += temp
to get the desired value changes.

I am trying to figure out what these temporary variables mean

def genfibon(n): #fib sequence until n
a=1
b=1
for i in range n:
yield a
t=a
a=b
b=t+b
Can someone explain the t variable? It seems like t=a so then a=b and then b=t because a=b and a=t. How does b=t+b?
Let's say a = 2 and b = 3.
t = a # now t = 2
a = b # now a = 3, but t is unchanged
b = t + b # now b = 5
The key is that second part. t = a means t gets the same value as a. It does not mean that t and a are now both the same thing.
You might try this in a Python prompt:
a = 3
b = a
a = 5
print(b) # still 3
It's called swapping of variables. how do you replace the values of variables?
as #smarx said, when a = 2 and b = 3, how do you make it a = 3 and b = 2?
when you do a = 3, the old value of a(2) is lost so you wont know what to set b with. so we store this in a temporary variable(t).
so,
t = a //(saves 2 in t)
a = b //(now both a and b have same values)
b = t //(b gets the old value of a)
// now a = old value of b
// and b = old value of a.
voila, the variables are swapped.
Well, that goes for swapping. which is only partly used in this code. the last statement b = t + b what the code is doing is, adding the old value of a with b(rather than replacing it). why? you get the next number in a fibonacci sequence by adding the previous 2.
2, 3, 5 is a fibonacci sequence since 5 = 2 + 3(given 2 and 3 are seed values). that's exactly what this code is doing.
In your first run
yield a # will return 1
t = a # which is 1
a = b # which is 1
b = t + b # which is 2 as t = 1 and b = 1
In your 2nd run
yield a # will return 1
t = a # which is 1
a = b # which is 2
b = t + b # which is 3 as t = 1 and b = 2
In your 3rd run
yield a # will return 2
t = a # which is 2
a = b # which is 3
b = t + b # which is 5 as t = 2 and b = 3
In your 4th run
yield a # will return 3
t = a # which is 3
a = b # which is 5
b = t + b # which is 8 as t = 3 and b = 5
And so on...
Let us go statement by statement.
t=a means value of a is stored in t.
a=b means value of b is stored in a. (Thus a now contains the next element in the series)
b=t+b means value of b is now t + b which means a+b since t now contains the value of a (According to first step).

Why do these two python functions return different results?

1-
def fib1(n):
a = 0
b = 1
while a < n:
print b
a = b
b = a+b
2-
def fib2(n):
a, b = 0,1
while a < n:
print b
a,b = b, b+a
On execution:
fib1(10) I got the wrong answer: 0 1 2 4 8
fib2(10) I got the right answer: 0 1 1 2 3 5 8
In fib 1
a = b
overwrites the value of a,
which means a is no longer the right value for the statement
b = a+b
However, in your second example both those things happen at the same time on the line a,b = a, b+a which means a is the right value still.
here's a quick answer:
the basic difference is the way the values of a and b are reassigned.
In fib1(), you have
a = b
b = a + b
while in fib2(), you have
a, b = b, b + a
Now, these two looks equal statements but they are not.
Here's why:
In fib2(), you assign the values of the tuple (b, b + a) to the tuple (a, b). Hence, reassignment of values are simultaneous.
However, with fib1(), you first assign value of b to a using a = b and then assign the value a + b to b. Since you have already changed value of a, you are in effect doing
b = a + b = b + b = 2b
In other words, you are doing a, b = b, 2b and that is why you are getting multiples of 2 rather than the fibonacci sequence.
fib1 contains a classic bug. It is in the same realm as that of swapping values of two variables. Think about how you would have done that in C or C++.
int a = 3;
int b = 5;
int temp;
temp = a; /* 3 */
a = b; /* 5 */
b = temp; /* 3, hence swapped */
There is a way to do without temp, although there are intermediate calculations involved. Now in Python, if you are not going to exploit the tuple unpacking feature, you have to involve a temp variable.
a = 3
b = 5
temp = a
a = b
b = temp
OR
a = 3
b = 5
a_ = (a+b)/2 - (a-b)/2 # 5.0
b_ = (a+b)/2 + (a-b)/2 # 3.0
Better use the tuple unpacking as in fib2.

difference between single and multiple assignments

I want to calculate the Fibonacci series in Python 3.5
If I do:
a = 0
b = 1
while b < 100:
print(b)
a, b = b, a + b
I get the right result, but if I do:
a = 0
b = 1
while b < 100:
print(b)
a = b
b = a + b
It simply does not work.
Why is this?
When you do this
a = b
b = a + b
then the assignment to a is executed first, and then the assignment to b, but at this time, a already has a new value. In effect, this is the same as
a = b
b = b + b # now a is the same as b
With the "double assignment", the two variables are updated at the same time
a, b = b, a + b
This assigns the tuple (b, a + b) to the tuple (a, b), using tuple-unpacking to distribute the values to a and b. You could think of this as being roughly equivalent to
temp = b, a + b
a = temp[0]
b = temp[1]
In the first iteration, the value of a changes to 1 which calculates b differently than in the second, where a + b = 2. In the first example, a + b = 1. At least, that's what it looks like to me.
In the first instance, inside the loop during the first run,
a, b = 1, 0+1
Leading a and b to be 1 and 1
In the second instance,
a = 1
b = 1 + 1
Leading a and b to be 1 and 2
The difference is that in the second instance, you're updating the value of b with an already updated value of a. Whereas in the first instance you're updating the value of b using the old value of a.

Categories