Python: Unexpected print values from within a simple function - python

I have created an simple, arbritrary function that prints out a value (1) based on what the first element from a randomly shuffled list is.
Looking at the code below: I am creating a variable and setting it to 1, then I'm a creating a small list (1,2,3) and then shuffling the list. The idea is, if the first element of that list (after shuffle) is 1 or 2, then print the value of 'correct', BUT if the first element of the list happens to be 3, set 'correct' to 0, and then run the function again. As you can see from the if statement, when 'value' is set to 0, I don't expect this to be printed at all because the function is being run again (chair()) before any printing takes place.
Having run this, I expected to find a print out of 5 values of 1. The problem is, I am seeing 0 values printed too. This seems like a very simple function, and I feel a little but stupid for not seeing why this is happenig. Any ideas?
def chair():
correct = 1
a = [1,2,3]
random.shuffle(a)
if a[0] == 3:
correct = 0
chair() #run function again without printing
print correct
for i in range(5):
chair()

Just calling chair() does not modify correct. You need to do correct = chair(). The problem with that is chair() does not return anything; it prints it. You should move the printing to outside of the function and return instead:
def chair():
correct = 1
a = [1,2,3]
random.shuffle(a)
if a[0] == 3:
correct = chair()
return correct
for i in range(5):
print chair()

Your function is recursive, so when you recall the function again to avoid printing, the function will still finish. If you added an else statement, you'd see those zeros disappear. Ex:
def chair():
correct = 1
a = [1,2,3]
random.shuffle(a)
if a[0] == 3:
correct = 0
chair() #run function again without printing
else:
print correct
for i in range(5):
chair()
edit: grammar
edit: example

Related

How to repeat a function till its return value matches its previous return value?

I have a Python function that returns a value.
def population_gen(P)
...
return fittest
Now, I need to write a piece of code that compares the "fittest" with last iteration of the function call population_gen(P) that returned "fittest" and stops when the current fittest becomes equal to the previous one.
What I have tried is the following:
def population_gen(P)
...
return fittest
gen_count = 0
max_gen_count = 10
while gen_count <= max_gen_count:
population_gen(Pop)
gen_count += 1
I can run this any number of times (11 in this case) and make sure that my code is working. But, I do not want to it run 11 times, rather keep the while loop running till the aforementioned condition is met. I also wanted to mention that this function generates a population from a given initial population. Then, I feed this function again with the population that it generates and successfully keep it running for as many times I want. But I cannot implement the condition of comparing the "fittest" value.
Please help. Thanks in advance!
I assume that you want to keep iterating through the loop if the current and last values of the function returned is not equal.
Theory:
You can declare two variables, one inside loop and one outside. The work of inside one is to get the value of function returned by the function, and the outside one will be used to keep check of the previous value, so that it doesn't get lost (I mean the previous value here).
Now, you know, how simple it is, let's implement it. First, for the example, I would be creating a function that returns a random value from a list.
import random # Importing random module for help in choosing random value
def foo():
_list = [1, 2, 3]
return random.choice(_list)
Now, we have our example function, let's create a loop to keep check. NOTE: The type of loop you are using can be used, but the more efficient one is to use for loop, as you can use range function there as suggested by #Jab.
It's time to declare variables and the loop:
var = None # Outside the loop, will be used as a container for previous returned value
for _ in range(1, 12): # range(min. value, max. value [not included])
a = foo() # Creating a variable 'a', that would be holding current returned value from the function
if var is not None and a == var: # For first iteration, it would be None but the value will be assigned to 'var' in for it's next iteration and checking it whether the prev. and current values are equal or not
break # Break the loop
var = a # Assigns 'var' the value if the loop is still running
Now, the above example can be used as the answer. But, what if you want to check it? So, following is the code provided with the example for debugging purposes:
import random
def func():
l = [1, 2, 3]
val = random.choice(l)
print(val) # Printing the value, for debugging purposes
return val
var = None
for x in range(1, 12):
a = func()
if var is not None and a == var:
print(f'\nSame values after {x} iterations') # It will show, after how many iterations the loop stopped
break
var = a
Now, I ran the above code 3 times, the following is the output:
OUTPUT:
>>> 3
>>> 3
>>>
>>> Same values after 2 iterations
>>> 2
>>> 3
>>> 2
>>> 2
>>>
>>> Same values after 4 iterations
>>> 2
>>> 2
>>>
>>> Same values after 2 iterations
I hope you understood the concept.
Use a new default variable set as maximum in the arguments. Like -
def population_gen(P, prev_fit = 99999): if prev_fit < population_gen(P): return prev_fit
Assuming you want to call the function population_gen until it's last two invocations return the same value. The output of population_gen becomes the input in the next iteration.
import random
def population(limit: int) -> int:
return random.randint(1, limit)
prev = None
cur = population(10)
while prev != cur:
prev = cur
cur = population(prev)
print(prev)

How does the code prints 1 2 6 24 as output and not 24 6 2 1

def recurr(k):
if (k>0):
result =k*recurr(k-1)
print(result)
else:
result=1
return result
recurr(4)
Output:
1
2
6
24
Because you're printing result after you recurse.
When you call recurr(4), the first thing it does is call recurr(3). This calls recurr(2), then recurr(1), and finally recurr(0). This last one is the base case, so it returns 1.
After that returns, you calculate result = k * 1, which is result = 1 * 1, then it prints that, so it prints 1 and then returns 1.
Then the previous recursion calculates result = k * 1, which is result = 2 * 1, then it prints that, so it prints 2 and returns it.
This repeats through all the recursions.
Its because you were printing result everytime you called it inside function instead of print what first call of function returned.
def recurr(k):
if (k>0):
return k*recurr(k-1)
return 1
print(recurr(4)) # -> 24
Because in every call of the function recurr() the print() function is executed.
If you want to print 24 that's the code:
def recurr(k):
if (k>0):
result =k*recurr(k-1)
else:
result=1
return result
print(recurr(4))
The recursion stack will print your message multiple times. This snippet may clarify why:
def factorial(k):
if (k>0):
print(f'factorial({k}) calls factorial({k-1})')
result = k*factorial(k-1)
else:
print(f'factorial({k}) is the base case')
result=1
return result
print(factorial(4))
you have to remove the print part in your function. Instead, you should write the code like this at the end of the code:
print(recurr(4))
The point is, the function is calling itself, and each time the function is called and processes the "if" block, it throws out a print. as for the order, the function evaluates the brackets inside out. As stated by #timgeb in comments,
recurr(4) --> 4*recurr(3*recurr(2*recurr(1*recurr(0))))
This evaluates recurr(0), which then successfully evaluates recurr(1) and so on.
The recursion in your code occurs on line 3, and the print statement occurs on line 4, after the recursion. When executing recurr(4), the entire code for recurr(3) (including the print statement for recurr(3)) is executed before the print statement for recurr(4).
Get 4 friends. Label them 1!, 2!, 3! and 4!. Tell them that if asked what their value is they must ask (n-1)! for their value, and then multiply by n, write it on a bit of paper and hand to the asker. All asking, must also be done on a bit of paper.
Now ask 4! for their value, when you get it shout it out.
Next tell them to do the same but whenever they pass a bit of paper to someone, they mast also shout out the value. Record what happens.
Which of the shouters is the one to keep?
When you use recursion, you build up a set of operation on the way down to the last call. Then you unroll them from the last, backwards up out to the first.
In this toy, you build up your result from the highest number, by putting your operation (k*next_value) at the bottom, and build it up. Then you get the result of each operation, from the top to the bottom.

Python programming function call scope changes

I am not a newbie to python. But recently I encountered an error, due to some misconception. Someone please help me to clarify it. Entire program is here : http://www.codeskulptor.org/#user39_cFs3Z8mAtf_0.py
I am having a function
def mc_trial(board, player):
"""
Plays a game starting with the given player by making random
moves and alternating between players.
"""
while board.check_win() == None:
# Get a random empty square
empty_squares = random.choice(board.get_empty_squares())
# Move the player in a random position
board.move(empty_squares[0], empty_squares[1], player)
# Switch the player
player = provided.switch_player(player)
# Game has ended
return
scores = [[0 for dummy in range(board.get_dim())] \
for dummy in range(board.get_dim())]
board_clone = board.clone()
for dummy in range(trials):
print board_clone ## Empty board
mc_trial(board_clone, player)
print board_clone #### Here value is changing after function call. How ??
My doubt is "board_clone" is passing to a function mc_trial(). the return statement there is not providing anything relating to return a value except None. But after the call, when I am printing "board_clone" the value is changing. I tried to clarify it with ipython through a sample program. But, there value remains unchanged as in the local scope . For clarification, i run a sample program, there it behaves as i expected.
def func1(var):
x = 0
while x < 1:
var[1:5]
x = x+1
return
var1 = [1,2,3,4,5,6,7,8,9]
print "B F", var1
func1(var1)
print "A F", var1
This is normal Python behaviour. Lists are passed by reference, so if you change the items in a list in a function, the changes will persist:
def f(mylist):
mylist[0] = 1
>>> l = [0, 0, 0]
>>> mylist(l)
>>> l
[1, 0, 0]
The reason your second example isn't changing the list is because the var[1:5] statement doesn't do anything. It just creates a temporary variable which is a slice of the var list, and then throws it away. It's just like saying a + 1; this would create a temporary variable but would not modify a even inside the function, let alone outside of it.
I'd guess your problem is that your "clone" has references to datastructs in the board object. The clone code doesn't appear in the link you posted?.. and as far as I can recall it's not an in-built python thing (I may be wrong there).?
Read this How to clone or copy a list?
and/or this
https://docs.python.org/2/library/copy.html

variable doesn't reset in while loop with function

I have never come across this before and wonder if anyone has a solution. I have a while loop with a function inside that returns an integer. The function takes a string and a list. The first iteration of the while loop returns the correct answer but on subsequent iterations the list seems to be empty even though the function does not change the list in any way. Also if i try to reset the list after the function in the while loop the new list also seems to be empty. It seems to be very strange behavior. Any explanation as to whats going on would be much appreciated. The code of the function inside the loop is quite long so at this stage I will avoid posting it. However if requested then I will post.
spectrum = [1,2,3,4,5,6]
leaderboard = ['zzz','xxx','yyy']
pep_scores = []
j=0
original_spectrum = spectrum
print len(original_spectrum)
while j < len(leaderboard):
x= linear_score(leaderboard[j],spectrum) #this function doesn't alter spectrum
print leaderboard[j], x
spectrum = original_spectrum #should reset spectrum even though it shouldn't be necessary to do that
print len(spectrum), len(original_spectrum) #prints 2 empty lists
pep_scores.append(x) #appends correct score on 1st iteration and '0' for all others
j=j+1
I had added print statements to try to resolve the problem, my original code did not contain 'original_spectrum = spectrum' or 'spectrum = original_spectrum' in the while loop. I don't understand why after 1 iteration 'origninal_spectrum' is an empty list. I haven't posted the function because I cannot see how it could be causing the problem. Please ask if you need more information.
To create copy of the list use copy_list = original_list[:].
So in your example:
spectrum = [1,2,3,4,5,6]
leaderboard = ['zzz','xxx','yyy']
pep_scores = []
j=0
original_spectrum = spectrum[:]
print len(original_spectrum)
while j < len(leaderboard):
x= linear_score(leaderboard[j],spectrum) #this function doesn't alter spectrum
print leaderboard[j], x
spectrum = original_spectrum[:] #should reset spectrum even though it shouldn't be necessary to do that
print len(spectrum), len(original_spectrum) #prints 2 empty lists
pep_scores.append(x) #appends correct score on 1st iteration and '0' for all others
j=j+1
Its because of that you define spectrum outside the function and its scope is global , and when you pass spectrum to your function as its the name of list any changes on it change it globally not local in your function ! and note that its just about mutable (like lists) objects . (Note : labels are pointer to special memory addresses ) (your copy command original_spectrum = spectrum just make 2 label for one object !!! )
for better understanding see the below example :
>>> a=[1,2,3]
>>> def f(s):
... s.remove(1)
...
>>> f(a)
>>> a
[2, 3]
>>> def f(s):
... s+=[1,2]
...
>>> f(a)
>>> a
[2, 3, 1, 2]
Now you have 2 choice :
make a copy of spectrum and pass that to function :
copy_spectrum = spectrum[:]
define spectrum inside the function and one outside for global usage !

I need help wrapping my head around the return statement with Python and its role in this recursive statement

No this isn't homework but it is on our study guide for a test. I need to understand the role the return statement plays and the role recursion plays. I don't understand why the function doesn't break after x = 1.
def thisFunc(x):
print(x)
if x>1:
result=thisFunc(x-1)
print(result)
return x+1
Sorry, I understand how elementary this is but I could really use some help. Probably why I can't find an explanation anywhere...because it's so simple.
edit: Why does it print out what it does and what and why is the value of x at the end? sorry if I'm asking a lot I'm just frustrated
When you enter the function with a value n>1 it prints the current value, and then calls it's self with n-1. When the inner function returns it returns the value n - 1 + 1 which is just n. Hence, the function prints out the value n twice, once before the inner recursion and once after.
If n == 1, which is the base case, the function only prints 1 once and does not call it self again (and hence does not get result back to print). Instead it just returns, hence why 1 is only printed once.
Think of it like an onion.
calling thisFunc(n) will result in
n
# what ever the output (via print) of thisFunc(n-1) is
n
I don't understand why the function doesn't break after x = 1.
But it does:
>>> ================================ RESTART ================================
>>> x = 1
>>> def thisFunc(x):
print("Function called on x-value: ", x)
if x > 1:
result = thisFunc(x-1)
print(result)
return x+1
>>> thisFunc(x)
Function called on x-value: 1
2
>>>
edit: Why does it print out what it does and what and why is the value of x at the end?
Well, it prints it out because you're telling it to. Try following the value of x as you go through the function ("x is one, one is not bigger than 1; return 1+1. Ok. [new case] x is two, two is bigger than 1..." and so on).
return and recursion are part and parcel of programming; return statements designates the end of a function (even if you might have several lines more of code) and they also pass data back to whatever asked them for it. In your case you're asking "what happens when x is 1, given these rules?"; the returned data is your answer.
Recursion is simply the matter of letting the function call itself, should it (you) need to. You simply tell the program that "hey, as long as x is bigger than 1, call this function [that just so happens to be the same function initially called] on it and let it do its thing". To get a better understanding of your function I'd suggest that you add the line "Function called on x-value: " to the first print statement inside the function, or at least something that lets you identify which printed line is x and which is result.
For a more in-depth explanation on recursion, I recommend Recursion explained with the flood fill algorithm and zombies and cats

Categories

Resources