g = 3; # A global
def sub1():
a = 5; # Creates a local
b = 7; # Creates another local
. . . <------------------------------ 1
def sub2():
global g; # Global g is now assignable here
c = 9; # Creates a new local
. . . <------------------------------ 2
def sub3():
nonlocal c: # Makes nonlocal c visible here
g = 11; # Creates a new local
. . . <------------------------------ 3
The book I am reading mentions the fact that a and b of sub1() are not visible in 3, although sub3() is more deeply nested than sub1() because a and b are dynamic stack variables.
sub3() can be executed without the execution of sub1() and hence a and b are not necessarily allocated memory. But it also says that c of sub2() is visible in 3. Why is the same logic not applied here?
var y;
function modify(x) {
var z = 5;
x += 2;
y += x + z
}
var x = 1,
y = 2,
z = 3
modify(x)
Above snippet result is x=1,y=10,z=3 Please explain this code. Thanks in advance
In the modify function, "x" is in the scope of modify, and is not going to use the x in the global scope. In addition, primitive types, such as numbers, are passed by value instead of reference. Therefore, x is always going to remain 1.
Also in the modify function, you are declaring a new variable of z in the scope of the modify function, so just like x, z is going to remain as 3.
Since y isn't declared in the function, it's going to use the global scope, so that's the only one that's going to change. In this case it's 2 + ((1 + 2) + 5), which is how you get 10.
Python beginner problem
(I am a beginner programmer)
So I was making a simple Fibonacci sequence generator and I made a working version, but I'm confused about how it works. In the code (lines 8-9), the first number (0) is being made the new value of the second value (1). But then that should make all the other numbers 0 as well, but it seems like the defining process is backward. Generally, the new value is on the left of the equal sign and the old value is on the right. But then that means everything should turn to 0. But actually, every number turns to 0 if I try to re-define the variables in the regular way (b = a; c = b). Why is this? I've attached my code at the bottom.
def seq_loop():
a = 0
b = 1
for i in range(15):
print(a)
c = a + b
a = b
b = c
print(seq_loop())
Have a good look at your code. Walk through it, and write down a,b and c in each iteration (or if you know how to use a debugger, set a break point in the loop te verify your variable's values). You'll see that your thinking is not right: in your first iteration: a = b is equivalent to a = 1 and b = c is equivalent to b = 1 + 1.
I am not sure that your interpretation of assignments is correct: An assignment goes right to left. The value (of the variable) on the right side of = is assigned to the variable on the left side of =
I don't really understand what you are asking, but a good way to understand code is to simply execute it by hand with pen&paper and keep a list of all the variables in scope and their current values. So, let's do that now.
In the first line, we define and initialize the variable a to the value 0. Our variables in scope and their values are { a = 0 }.
In the second line, we define and initialize the variable b to the value 1. Our variables in scope and their values are { a = 0; b = 1 }.
In the first line of the loop, we print the current value of the variable a, which we can look up in our variable list is 0. We haven't assigned any variables, so our variables in scope are still unchanged: { a = 0; b = 1 }. And the console looks like this:
0
In the second line of the loop, we define and initialize the variable c to the result of evaluating the expression a + b. We have to dereference the two variables, i.e. look up their values in our list, and their values are 0 and 1. 0 + 1 is 1, which means we initialize c to 1. Our variables in scope and their values are { a = 0; b = 1; c = 1 }.
In the third line of the loop, we assign the variable a. The value we assign to the variable a is the current value of the variable b. So, we look at our variable list, and we see that the current value of b is 1, which means we assign 1 to a. Our variables in scope and their values are { a = 1; b = 1; c = 1 }.
In the fourth line of the loop, we assign the variable b. The value we assign to the variable b is the current value of the variable c. So, we look at our variable list, and we see that the current value of c is 1, which means we assign 1 to b. Our variables in scope and their values are { a = 1; b = 1; c = 1 }.
After the fourth line of the loop, the variable c goes out of scope. Our variables in scope and their values are now { a = 1; b = 1 }.
As you can see, we started the first iteration of the loop with { a = 1; b = 0 } but after the first iteration of the loop, we have { a = 1; b = 1 }, which is what we start the second iteration of the loop with. It is important that something has changed here, otherwise each iteration of the loop would do the same thing, and we would always get the same result.
So, let's look at the second iteration of the loop.
In the first line of the loop, we print the current value of the variable a, which we can look up in our variable list is 1. We haven't assigned any variables, so our variables in scope are still unchanged: { a = 1; b = 1 }. And the console looks like this:
0
1
In the second line of the loop, we define and initialize the variable c to the result of evaluating the expression a + b. We look up their values in our list, and their values are 1 and 1. 1 + 1 is 2, which means we initialize c to 2. Our variables in scope and their values are { a = 1; b = 1; c = 2 }.
In the third line of the loop, we assign the variable a. The value we assign to the variable a is the current value of the variable b. So, we look at our variable list, and we see that the current value of b is 1, which means we assign 1 to a. Our variables in scope and their values are { a = 1; b = 1; c = 2 }.
In the fourth line of the loop, we assign the variable b. The value we assign to the variable b is the current value of the variable c. So, we look at our variable list, and we see that the current value of c is 2, which means we assign 2 to b. Our variables in scope and their values are { a = 1; b = 2; c = 2 }.
After the fourth line of the loop, the variable c goes out of scope. Our variables in scope and their values are now { a = 1; b = 2 }.
Now for the third iteration.
In the first line of the loop, we print the current value of the variable a, which we can look up in our variable list is 1. We haven't assigned any variables, so our variables in scope are still unchanged: { a = 1; b = 2 }. And the console looks like this:
0
1
1
In the second line of the loop, we define and initialize the variable c to the result of evaluating the expression a + b. We look up their values in our list, and their values are 1 and 2. 1 + 2 is 3, which means we initialize c to 3. Our variables in scope and their values are { a = 1; b = 2; c = 3 }.
In the third line of the loop, we assign the variable a. The value we assign to the variable a is the current value of the variable b. So, we look at our variable list, and we see that the current value of b is 2, which means we assign 2 to a. Our variables in scope and their values are { a = 2; b = 2; c = 3 }.
In the fourth line of the loop, we assign the variable b. The value we assign to the variable b is the current value of the variable c. So, we look at our variable list, and we see that the current value of c is 3, which means we assign 3 to b. Our variables in scope and their values are { a = 2; b = 3; c = 3 }.
After the fourth line of the loop, the variable c goes out of scope. Our variables in scope and their values are now { a = 2; b = 3 }.
And this is the fourth iteration of the loop.
In the first line of the loop, we print the current value of the variable a, which we can look up in our variable list is 2. We haven't assigned any variables, so our variables in scope are still unchanged: { a = 2; b = 3 }. And the console looks like this:
0
1
1
2
In the second line of the loop, we define and initialize the variable c to the result of evaluating the expression a + b. We look up their values in our list, and their values are 2 and 3. 2 + 3 is 5, which means we initialize c to 5. Our variables in scope and their values are { a = 2; b = 3; c = 5 }.
In the third line of the loop, we assign the variable a. The value we assign to the variable a is the current value of the variable b. So, we look at our variable list, and we see that the current value of b is 3, which means we assign 3 to a. Our variables in scope and their values are { a = 3; b = 3; c = 5 }.
In the fourth line of the loop, we assign the variable b. The value we assign to the variable b is the current value of the variable c. So, we look at our variable list, and we see that the current value of c is 5, which means we assign 5 to b. Our variables in scope and their values are { a = 3; b = 5; c = 5 }.
After the fourth line of the loop, the variable c goes out of scope. Our variables in scope and their values are now { a = 3; b = 5 }.
Let's do one last iteration of the loop.
In the first line of the loop, we print the current value of the variable a, which we can look up in our variable list is 3. We haven't assigned any variables, so our variables in scope are still unchanged: { a = 3; b = 5 }. And the console looks like this:
0
1
1
2
3
In the second line of the loop, we define and initialize the variable c to the result of evaluating the expression a + b. We look up their values in our list, and their values are 3 and 5. 3 + 5 is 8, which means we initialize c to 8. Our variables in scope and their values are { a = 3; b = 5; c = 8 }.
In the third line of the loop, we assign the variable a. The value we assign to the variable a is the current value of the variable b. So, we look at our variable list, and we see that the current value of b is 5, which means we assign 5 to a. Our variables in scope and their values are { a = 5; b = 5; c = 8 }.
In the fourth line of the loop, we assign the variable b. The value we assign to the variable b is the current value of the variable c. So, we look at our variable list, and we see that the current value of c is 8, which means we assign 8 to b. Our variables in scope and their values are { a = 5; b = 8; c = 8 }.
After the fourth line of the loop, the variable c goes out of scope. Our variables in scope and their values are now { a = 5; b = 8 }.
I hope it is somewhat clearer now.
One thing that is very important in programming is naming. Good names should be intention-revealing. In this case, none of the names are very good: what does the name a tell you about what the intent of the programmer is? The same goes for b, c, and i. seq_loop is also not very intention-revealing, i.e. what does this function actually do? It prints the Fibonacci sequence. How can I tell from the name that it prints the Fibonacci sequence? Well, I simply can't!
So, here is the code with some better names, which should clear up some confusion:
def print_fibonacci_sequence():
previous = 0
current = 1
for _ in range(15):
print(previous)
after = previous + current
previous = current
current = after
print(print_fibonacci_sequence())
You might ask yourself "How is _ a more intention-revealing name than i?" The reason is that _ has a well-known meaning in the Python community: it is used as the name for a variable that is being ignored. Which is exactly what we are doing in this case.
Also, why after and not next? next is already defined in Python and it is considered bad style to shadow or even worse redefine Python builtins.
There are a couple of other oddities in the code. For example, the function prints the elements of the Fibonacci sequence and it doesn't return anything. And then you call the function and print the result of the call … but there is no result because the function doesn't return anything! Renaming the function to have print in its name so that it is clear that it doesn't return anything but prints it, makes that mistake more obvious:
print(print_fibonacci_sequence())
You can immediately see that you print something which prints something, which makes no sense. It should just be
print_fibonacci_sequence()
Another oddity is that the function always prints the first 15 terms of the Fibonacci sequence. Usually, you would want to let the caller decide how many terms to print. Maybe the caller only needs 3? Maybe 20? So, let's do that:
def print_fibonacci_sequence(number_of_elements):
previous = 0
current = 1
for _ in range(number_of_elements):
print(previous)
after = previous + current
previous = current
current = after
print_fibonacci_sequence(15)
Speaking of letting the caller decide what to do, what if the caller doesn't want to print the Fibonacci sequence? What if the caller wants to format it as HTML or insert it into an Excel table?
You should always separate computation from input/output. So, in this case, instead of printing the Fibonacci sequence, we will return the Fibonacci sequence, and then the caller can print it if they want to:
def fibonacci_sequence(number_of_elements):
fibonacci_sequence = []
previous = 0
current = 1
for _ in range(number_of_elements):
fibonacci_sequence.append(previous)
after = previous + current
previous = current
current = after
return fibonacci_sequence
print(fibonacci_sequence(15))
Actually, if you think about it, having the caller pass the number of terms as an argument is still somewhat restrictive. What if the caller doesn't want the first n terms, but the first terms smaller than n? In that case, they would have to compute the Fibonacci sequence first to see how many terms there are smaller than n and then ask for that number of terms of the Fibonacci sequence, which obviously defeats the purpose of having the function in the first place.
The best solution for the caller would be to produce an infinite number of terms and let the caller decide which condition to use to decide how many terms to take:
def fibonacci_sequence():
previous = 0
current = 1
while True:
yield previous
after = previous + current
previous = current
current = after
Now you can use it like this:
from itertools import islice, takewhile
first_15_terms = islice(fibonacci_sequence(), 15)
terms_less_than_100 = takewhile(lambda term: term < 100, fibonacci_sequence())
And you can decide what to do with the result. For example print it:
for term in first_15_terms:
print(term)
for term in terms_less_than_100:
print(term)
Or you can turn it into a list:
list_of_first_15_terms = list(first_15_terms)
list_of_terms_less_than_100 = list(terms_less_than_100)
And many other things.
This is a general principle in programming, software engineering, and API design: not only separate input/output from computation, but also break up the computation into separate parts for producing values, consuming values, transforming values, filtering values, representing values as strings (to be output later), parsing string representations into values (coming in from the outside), and so on.
In one sentence, we could say: separate the things that change.
for beginner type question but can somebody tell me why does python 3 dont overwrite the below variable
in this line output = output + s1/output = output + s2
in short can anyone tell inner workings of this==>output = output + s2
is it getting assign ref variable? or storing the value in it?
s=input("enter your string: ") #A132BC
S1=''
S2=''
output=''
for x in s:
if x.isalpha():
S1=S1 + x
else:
S2=S2 + x
for s1 in sorted(S1):
output = output + s1 #output = '' + A==> output = 'A'
for s2 in sorted(S2):
output = output + s2
print(output)
In Python everything is an object that is treated as references.
S1 = "" creates the value "" and stores the reference into the name S1. If later you do S1 = "Hello, world!, the interpreter creates a new value an assigns this new reference to S1.
The same behaviour occurs for output, at first it stores a reference to "" and when you do output = output + s1 a new value that is the concatenation of output and s1 is created and the new reference is assigned to output.
Not that this can be written in a more concise way as output += s1.
This link contains useful stuff about Python types an assignment.
Note
As pointed out in the comments there is some subtleties with assignments, you can read [this](However, I'll update my answer concerning a missing note about mutable/immutable behaviour.) blog post for even more details.
An interesting and quite misleading behaviour for beginners pointed out is that there are differences in the use of operator +=.
For int, str or bool this operator effectively creates a new value from the old one, the original value is not mutated.
For sequences this operator behaves has a mutating operator.
For instance compare the output of those two functions:
def modify(int_value):
int_value += 1 # Does not add 1 in-place
def modify(array):
array += [1] # Mutates the array in-place
I'm trying an ultra simple novice exercise.
The objective of the exercise was to create a fibonacci pattern, I tried two methods that I thought were going to give the same result. But fires some reason they don't, I can't understand why.
Any ideas?
CODE 1
a = 0
b = 1
while b < 100:
print(b)
a = b
b = a + b
CODE 2:
a, b = 0, 1
while b < 100:
print(b)
a, b = b, a + b
In "CODE 1", a = b makes the next line equivalent to b = b + b, which is not correct.
In "CODE 2", a,b=b,a+b is essentially new_a = old_b; new_b = old_a + old_b. The new values are computed from the old values, then the new values are assigned to the variables. This computes the fibonacci series correctly.
To do it correctly in "CODE 1" a temporary variable is needed:
t = a
a = b
b = t + b # use original a saved in t to compute b
a,b=b,a+b eliminates the need for the temporary variable.