Python passing local variables for modification in function - python

and I'm trying to figure out how I would go about passing local variables to a function and then returning the modified values. I've written the code below:
def main():
change = 150
coins = 0
quarter = 25
while (change >= quarter):
change = change - quarter
coins += 1
print(coins)
if __name__ == "__main__":
main()
But I'd like to be able to extract the modification of the change and coins variables like so:
def main():
change = 150
coins = 0
quarter = 25
while (change >= quarter):
count (change, coins, quarter)
def count(change, count, n):
change = change - n
count += 1
return change, count
if __name__ == "__main__":
main()
However, I know this isn't the way to do it. From what I understand, there could be an issue with trying to return multiple variables from the function, but it also seems like there an issue when I try to even modify only the change variable within the count function.
I would really appreciate any advice.

You're returning two values from count(), so you should capture those values when you call it:
while (change >= quarter):
change, coins = count(change, coins, quarter)
Modifying ch and co inside count() will not affect the outer values change and coins.

Related

Recursive behavior

Why does the following executes such that the print statement is called as often as it recursed but the count variable, count, when x == 1 is never reached.
def count_bits(n, count = 0):
x = n % 2
if n == 1:
return count + 1
if n < 1:
return count
if x == 1:
count += 1 # when x == 1
count_bits(int(n/2), count)
print("counter")
return count
why is it necessary to recurse with the return statement? Because if the recursive call is above the return statement the code
returns the wrong output but with the recursive call called with
return keyword, everything works well. Typically, the print statement
prints 'counter' as often as it recursed showing that the recursive call
works.
On the other hand, if "return" follows after the recursive call, it returns the count from the base condition, correctly.
def count_bits(n, count = 0):
x = n % 2
if n == 1:
return count + 1
if n < 1:
return count
if x == 1:
count += 1
return count_bits(int(n/2), count)
You have to return recursion result, as reccurent function meaning is to count current step you have to get result of previous step
F_k = F_k-1 * a + b # simple example
Means that you have to get result of F_k-1 from F_k and count current result using it.
I advised you to use snoop package to debug your code more efficient , by this package you can track the executing step by step.
to install it run:
Pip install snoop
Import snoop
add snoop decorator to count_bits()
for about the package see this link
https://pypi.org/project/snoop/
the difference in the output between the two methods is because of the way in which python handles fundamental data types. Fundamental data types such as float, ints, strings etc are passed by value, whereas complex data types such as dict, list, tuple etc are passed by reference. changes made to fundamental data types within a function will therefore only be changed within the local scope of the function, however changes made to a complex data type will change the original object. See below for an example:
x = 5
def test_sum(i : int):
print(i)
i += 5
print(i)
# the integer value in the global scope is not changed, changes in test_sum() are only applied within the function scope
test_sum(x)
print(x)
y = [1,2,3,4]
def test_append(l : list):
print(l)
l.append(10)
print(l)
# the list in the global scope has '10' appended after being passed to test_append by reference
test_append(y)
print(y)
This happens because it's far cheaper computationally to pass a reference to a large object in memory than to copy it into the local scope of the function. For more information on the difference, there are thousands of resources available by searching "what is the difference between by reference and by value in programming".
As for your code, it seems to me the only difference is you should alter your first snippet as follows:
def count_bits(n, count = 0):
x = n % 2
if n == 1:
return count + 1
if n < 1:
return count
if x == 1:
count += 1 # when x == 1
# assign the returned count to the count variable in this function scope
count = count_bits(int(n/2), count)
print("counter")
return count
The second code snippet you wrote is almost identical, it just doesn't assign the new value to the 'count' variable. Does this answer your question?

python local variable sent to function, modified, but was not passed back to program

I'm writing a program for a class, which we were instructed to write a unique program of our own. I decided to make one which determines a user's letter grade based off of their average out of 100.
My problem is, I passed my grade counter to my function, but when I try to return it, it remains its starting value at which I defined it.
#4. Increment grade count by 1
Gather_Intel(grade_list, grade_count)
print (grade_list, grade_count)
def Gather_Intel(GL, GC):
g = 0
while g >= 0:
g = int(input("Please input a grade (-1 to quit): "))
GL.append(g)
GC = GC + 1
GL.sort
GL.remove(-1)
return GL, GC
Is there something I missed that I'm not seeing?
You forgot to re-assign the returned values:
grade_list, grade_count = Gather_Intel(grade_list, grade_count)
Your function does return those values, but without assigning those returned values to something you are effectively ignoring the results.

Global list doesn't contain value at another function

I want to make a global list and I saved a value in my global list (def rand()).
Whatever I save, my saved value doesnt include at another function except rand().
What am I missing?
sayi = []
def rand():
global sayi
initial = 1000
for i in range(1000,10000):
initial +=1
sayi.append(initial)
print sayi[43]
def main():
rand()
print len(sayi) # Shows 0 but I have added value at rand funct. with append funct.
main()
I'm going to assume you're new to python. INDENTATION MATTERS. Not trying to be mean, but I've noticed that trips a lot of people up. Here's your modified code.
sayi = []
def rand():
global sayi
initial = 1000
for i in range(1000,10000):
initial +=1
sayi.append(initial)
print sayi[43]
def main():
rand()
print len(sayi) # Shows 0 but I have added value at rand funct. with append funct.
main()
you have everything working, your indentation is just a little off.

Local variables in Python

I wrote this small program to print multiplication tables. I was understanding the local variables then I added two variables with same name in each function. but it is running and I am not getting any 2 variables with same name error. Please help me understand the idea here -
def printMultiples(n):
i = 1
i = 5
while i <= 10:
print n*i, '\t',
i = i + 1
print
def printMultTable():
i = 1
i = 10
while i <= 10:
printMultiples(i)
i = i + 1
The variable i gets defined as soon as the function is run, it does not wait until the lines
i = 1
i = 10
are run. When the code is compiled, Python looks at every variable that is assigned in the function, and creates definitions for any that aren't declared to be global or nonlocal.
Each i = line will just change the value, it doesn't cause it to be defined again.
Here's what's happening in your script:
i = 1
creates the variable i and assigns the value 1 to it
i = 5
replaces the value held in i with 5
while i <= 10:
starts your loop
print n*i, '\t',
The first iteration of the loop will print n * 5 and a tab character
i = i + 1
increments i by one
There aren't two variables with the same name, there's one variable that is being assigned to twice.
i = 1 # i is declared and assigned to 1
i = 5 # the same i is reassigned to 5
In python, symbols are just names for variables. They are do not allocate memory as they do for say, C/C++. So what you are doing is simply reassigning the values to 'i' in each case.
You're not actually creating two variables with the same name; your second i = is reassigning i to a new value, same as i = i + 1 is setting i to the value of i + 1.
There are more Pythonic ways to deal with looping a fixed number of times, by the way:
for i in range(1, 11):
printMultiples(i)
This will execute printMultiples for values starting in 1 and less than 11.

python scooping and recursion

I am struck in a small recursive code. I have printed output and it prints fine but when I try to put a counter to actually count my answers, it gives me scooping errors.
total = 0
def foo(me, t):
if t<0:
return
if t==0:
total = total+1
return
for i in range(1, me+1):
total = total+1
return foo(i, t-i)
it says local variable referenced before assignment, well, I am trying to refer total in the first line.... Its not about global variables, I have tried to use global as well but in vain.
This is pure scooping issue, any ideas?
As mentioned by others, you need the global statement for total. Also, as noted by Svante, the for loop is unnecessary as coded since i is always 1. So, with an equivalent version of your code:
total = 0
def foo(me, t):
global total
if t < 0:
return
total = total + 1
if t == 0:
return
return foo(1, t-1)
foo(99, 100)
print total
It should be easier to see that foo(99, 100) will indeed be 101 since you're essentially counting down from 100 to 0. I'm not sure why you think otherwise?
You forgot to make sure to set total as a global in your function. You said "I have tried to use global as well but in vain." but when I try it below it doesn't throw any error:
total = 0
def foo(me, t):
global total
if t<0:
return
if t==0:
total = total+1
return
for i in range(1, me+1):
total = total+1
return foo(i, t-i)
I'm not sure you really know what you are trying to do...
(at least if you say that adding the global keyword gives incorrect results, but silences the errors)
you do need the statement "global total" if you are going to to try to reference total (which you are doing)
(what are you expecting when you execute foo(99, 100)?)
maybe your boundary conditions are wrong?
'cause with the arguments (99, 100)
foo will skip the two if statements
loop in the following loop:
for i in range(1, 100):
total += 1
return foo(i, 100-i)
which really is equivalent to
else:
total += 1
return foo(1, 99)
(like Svante was saying)
based on your two if conditions
foo(1,99) will correctly generate total += 100
(99 times it will execute your "else" statement bringing the total to 100, and then finally it will reach t == 0 and execute the last final if where it will push the total to your "incorrect" 101)
you should also use elif for your second case
As a generic advice, recursion should always use return values, and not global variables. Recursion has already its own load of complexity, increasing it with side-effects and not clear interfaces will make it even worse.
You should try something in the lines of this:
def foo(me, t):
if t<0:
return 0
if t==0:
return foo(me, t+1)
return foo(me-1, t)
for i in range(1, me+1):
tot = foo(i, t-i)
return tot
Note: this code is wrong, it will not solve your problem and it will not even work on its own; I put it just to give a kind of idea of how to design a recursion that is easier to manage.
Thanks people, thanks youarf, Liffredo.
I was wrong, I didnt notice that I was returning before adding-up things, loop was only running once, I have fixed the code. It is like this:
def foo(me, t):
if t<0:
return 0
if t==0:
return 1
toreturn = 0
for i in range(1, me+1):
toreturn = toreturn + foo(i, t-i)
return toreturn
This snippet is for this problem at http://projecteuler.net/index.php?section=problems&id=76

Categories

Resources