This code has me lost. When run, it outputs sequences which I finds strange:
def print_n(number):
if (number <= 0):
return None
else:
print number
print_n(number-1)
print_n(number-1)
print_n(4)
I thought it would output this sequence:
4,3,2,1,1,2,1,3,2,1
however it actually outputs:
4,3,2,1,1,2,1,1,3,2,1,1,2,1,1
I tried to draw the stack diagram of this function but when I get lost at the second appearance of the print_n(number-1).
I can understand this program without the second appearance of the print_n(number-1), as it's just normal recursion. However, the second print_n(number-1), seems much more complicated than I expected, I don't know how to trace this function call and explain the result...
Since the if block has an unconditional return, you can remove the else and the program will continue to behave the same way.
def print_n(number):
if (number <= 0):
return None
print number
print_n(number-1)
print_n(number-1)
Here, it's more apparent what is going on: You print number, and then call print_n twice using number-1. You can work backwards to derive the output.
print_n(1) prints "1"
print_n(2) prints "2" plus "1" plus "1": "211"
print_n(3) prints "3" plus "211" plus "211": "3211211"
print_n(4) prints "4" plus "3211211" plus "3211211": "432112113211211"
I liked the answer of Kevin, but let me add a few words towards "understanding recursion":
I often suggest using sheets of paper representing the stack. each sheet contains its local varaibles and current state - and you can mark the line you are "processing" with a pen.
Use a separate sheet as output / console.
This gives you a very good understanding of what is going on.
Of course, following your code in a debugger and examining the stack trace can be helpful as well. But try the paper-approach first!
Related
So here's my code.
def bubblesort(list):
global step
global oldlist
print("""
ORIGINAL LIST""")
print(list)
for i in range(len(list)):
for j in range(len(list)-1):
if float(list[j])>float(list[j+1]):
list[j], list[j+1] = list[j+1], list[j]
if oldlist==list:
**end(list)**
else:
oldlist=list
step=step+1
print("""
STEP""",step)
print(list)
end(list)
def end(list):
global step
step=step+1
print("""
STEP""",step)
print(list)
step=0
oldlist=[]
list=[]
number=int(input("How many numbers do you want to input to sort? : "))
for i in range(1,number+1):
value=float(input("INPUT NUMBER : "))
list.append(value)
bubblesort(list)
The issue is the bit of code which I have is "end(list)" bare in mind I've included the ** to make it easier to see on here it's not actually in the code. It simply won't call the subroutine when I ask it to. I know it definitely runs through the if since if i put a "print" or "break" in they both work it just won't jump to a sub-routine. Furthermore, the time I call that subroutine later on in the code works and does go to the subroutine. So i'm a bit lost as to what I've done wrong here. Any help? Would be much appreciated :)
There are quite a few things wrong with your code, and your question. Let's go through them:
First of all, the formatting was not great (I've suggested an edit). This might not sound like a big deal ("Hey, as long as it works...") but it's actually crucial: I work with python every day, and I had trouble understanding your code
You're talking about subroutines. In python, we usually refer to those as functions, or methods.
You're using globals variables all over the place. This might work in little toy examples like this one, but it will fall apart VERY fast
As David Buck said, list is one of the basic data structures: 1 in an instance of int and [1,2,3] is an instance of list). It's a really bad idea to override it.
I'm not sure what you're trying to do with the end() function. It seems do very little, and what it does is not related to its name...
You create an oldlist list but never really do anything with it. What is it supposed to to ?
With that in mind, here is my proposition:
def main():
# I like to put the main code in a "main" function, so that it can be at the top
# of the file. We'll call main() from the bottom of the file
# Make our program pretty, with a little branding
print("===== Number Sorter 9000 =====")
# 'numbers' is not the name of anything yet, so we can use it safely
numbers = []
# This will loop forever, unless we tell it to stop. It allows us to skip the
# part where you ask the user for a number of values: Simply enter the values
# one by one, and press enter once last time when done.
while True:
value = input(f"Number {len(numbers)+1} (leave empty to continue): ")
# Decide what to do with the value we received. If it's a number,
# add it to our list, if it's empty, stop collecting numbers
if value:
# Make sure the value is a number ()
value = float(value)
# Add the number to the list
numbers.append(value)
else:
# This will get us out of the number-asking loop
break
print("Number Sorter 9000 will now sort your numbers")
sorted_numbers = bubblesort(numbers)
print("Number Sorter 9000 has sorted your numbers:")
print(sorted_numbers)
def bubblesort(numbers):
# Here I've removed things that were not doing much.
# There are some ways to improve the algorithm itself, but I'll let you do that
for i in range(len(numbers)):
for j in range(0, len(numbers)-i-1):
if numbers[j] > numbers[j+1]:
numbers[j], numbers[j+1] = numbers[j+1], numbers[j]
# We 'return' the result from the function, so that code that calls the
# bubblesort() function can use the result
return numbers
# Lastly, we call the "main" function to get everything started. Without this
# line, nothing happens: We've just explained to the computer how to do some
# stuff, but we haven't asked it to *DO* anything
main()
Well, I hope this was not too much information. I've tried to keep things simple, but feel free to ask if something is not clear
I'm a brand new programming graduate student and am having a bit of trouble. I'm working through a textbook problem that wants me to take a positive integer and print the Collatz sequence of that number.
while num !=1:
print(num)
if num%2==0:
num = num//2
else:
num = 3*num+1
print(1)
Now, this code works. And I get the mathematical logic. But there's parts I don't understand.
Firstly, the print(num), this is done so the code prints the input number since that starts the sequence. But, what is the logic/explanation to having this at the front of the loop?
Second, for num = num//2 and num = 3*num+1, why is that all you need for the code to run? In the end, our goal is to print the whole sequence until the input gets to 1. I thought you'd need an accumulator up top. i.e. lst = [] to append each value into that list and then return the list. Why does just re-labeling them num = work? Each time it iterates, wouldn't the prior value be deleted since it isn't stored anywhere?
Lastly, why do we not need to end the loop with a return? How does it know to print the whole sequence of numbers? It ends with print(1) because every input needs to end with that, and it terminates before 1. However, I have not called upon the function (it's a function on my end, not just a while loop) to take action. It just...did it.
I'm sorry if that's a bit confusing, but I'm trying to understand the correct code answer. I've mostly been doing accumulators and stuff, so I'm not sure why this didn't need one, what the num = did, and how you can just end it with print(1) and the whole sequence appears.
Firstly, the print(num), this is done so the code prints the input number since that starts the sequence. But, what is the logic/explanation to having this at the front of the loop?
It's placed where it is because it's not just there to print the input number. It's there to print whatever num happens to be at that point in the code, each time that point in the code is reached. On the first iteration, num is the first element of the sequence. On the second iteration, num is now the second element of the sequence. On the third iteration, num is the third element, and so on. This print prints every element of the sequence, except 1, because the loop breaks at that point, which is why there's a separate print(1) after the loop.
Second, for num = num//2 and num = 3*num+1, why is that all you need for the code to run? In the end, our goal is to print the whole sequence until the input gets to 1. I thought you'd need an accumulator up top. i.e. lst = [] to append each value into that list and then return the list. Why does just re-labeling them num = work? Each time it iterates, wouldn't the prior value be deleted since it isn't stored anywhere?
print(num) prints each sequence element as it's computed, so the program doesn't need to explicitly save the elements. The program does forget the previous values, but they were already printed. Remembering the printed output is some other tool's job - for example, if you run this with stdout directed to a file, the printed output is written into the file.
Lastly, why do we not need to end the loop with a return? How does it know to print the whole sequence of numbers? It ends with print(1) because every input needs to end with that, and it terminates before 1. However, I have not called upon the function (it's a function on my end, not just a while loop) to take action. It just...did it.
return has two jobs: it ends the current function execution, and it sets the return value. If execution reaches the end of a function without executing a return, execution of the function still ends, with a return value of None. return isn't involved in printing the output. That's print's job, as explained above.
As for not calling the function, we can't answer what's going on with that. We would need to see what you actually ran, including the actual function.
this is how the output "magically appears" without a list
see #1
you always return from a function ... in this case you are returning None, instead you are printing the list
it might help to put a time.sleep in there(inside your loop) to visualize whats happening
this site : python tutor - see how it works
is helpful for visualizing code execution
This is probably a dumb question, but I'm new to programming and I have a recursive function set up that I'm trying to figure out. For any print function in Python, is it necessarily true that lines are printed in the order that they are written in the script OR for larger outputs, is it possible that smaller length outputs can get printed first in the console even though the print statement is later in the code (maybe due to some memory lag)?
Example:
def test_print():
#don't run this, but was meant for scale. Is there any chance the 1 would print before the list of lists?
print([[i for i in range(10000)] for j in range(10000)])
print(1)
Print statements pile output into stdout in the order the code was written. Top to bottom. It isn't possible any other way because that's the way the code is interpreted. Memory lag doesn't play any role here because the output to your console is a line for line rendition of the data that was piled into stdout. And the order the data was written to it can't change, so you'll maintain chronology. Of course, you can always play around with the how the print function itself works. But I wouldn't recommend tampering with standard library functions.
As said above, print() function is executed in the order which they are in your code. But you yourself can change the order in which you want it executed, after all you have every right to instruct the code to do whatever you want.
You'll always get the same order in the output as the order you execute print() functions in Python.
I have a piece of coding that is most basically a quiz. I had error handling so that if someone pressed a letter or anything other than a number, it would carry on with the quiz instead of letting the person attempt another question. (For example, if question 5 was 2+3 and they entered t, then it would carry on and not give them a different question for question 5).
I tried to update the coding, so it would loop:
def random_question():#defines function to get random question
count = 0#equates count to 0
for number in range (0,10):#makes the code generate the question 10 times
try:#the code makes it so the computer tries one thing and is the beggining
questionList = [random_sum,random_subtraction,random_times]#puts functions in a list to be called on
randomQuestion = random.choice(questionList)#calls on the list to generate the random questions
randomQuestion()#calls on variable
except ValueError:#if there is a value error or a type error it will notice it and try to stop it
print ("Please enter a number")#prints out the statement if there is a type error or a value error
else:
break
random_question()#calls on the function random_question
However, it comes up with a syntax error, and highlights the 'except' part next to the ValueError.
Any help as to why this is would be much appreciated.
Your except statement should have the same indention as your try statement. In your sample code it is indented an extra tab which would cause that error.
Python takes indention seriously and it is often the culprit. I'm unclear if your def line is a place holder or if this code is part of it, but if this code is part of the function definition you have other indention issues to worry about.
I'd suggest going through it carefully and making sure everything is lined up properly. The basic rule of thumb is, if something is part of something else, it is indented under it.
def something():
step 1
step 2
if (condition):
the true thing
else:
the false thing
while (something):
repeat something
this is not part of the function anymore
I'm pretty new to this whole "programming thing" but at age 34 I thought that I'd like to learn the basics.
I unfortunately don't know any python programmers. I'm learning programming due to personal interest (and more and more for the fun of it) but my "social habitat" is not "where the programmers roam" ;) .
I'm almost finished with Zed Shaws "Learn Python the Hard Way" and for the first time I can't figure out a solution to a problem. The last two days I didn't even stumble upon useful hints where to look when I repeatedly rephrased (and searched for) my question.
So stackoverflow seems to be the right place.
Btw.: I lack also the correct vocabular quite often so please don't hesitate to correct me :) . This may be one reason why I can't find an answer.
I use Python 2.7 and nosetests.
How far I solved the problem (I think) in the steps I solved it:
Function 1:
def inp_1():
s = raw_input(">>> ")
return s
All tests import the following to be able to do the things below:
from nose.tools import *
import sys
from StringIO import StringIO
from mock import *
import __builtin__
# and of course the module with the functions
Here is the test for inp_1:
import __builtin__
from mock import *
def test_inp_1():
__builtin__.raw_input = Mock(return_value="foo")
assert_equal(inp_1(), 'foo')
This function/test is ok.
Quite similar is the following function 2:
def inp_2():
s = raw_input(">>> ")
if s == '1':
return s
else:
print "wrong"
Test:
def test_inp_2():
__builtin__.raw_input = Mock(return_value="1")
assert_equal(inp_1(), '1')
__builtin__.raw_input = Mock(return_value="foo")
out = StringIO()
sys.stdout = out
inp_1()
output = out.getvalue().strip()
assert_equal(output, 'wrong')
This function/test is also ok.
Please don't assume that I really know what is happening "behind the scenes" when I use all the stuff above. I have some layman-explanations how this is all functioning and why I get the results I want but I also have the feeling that these explanations may not be entirely true. It wouldn't be the first time that how I think sth. works turns out to be different after I've learned more. Especially everything with "__" confuses me and I'm scared to use it since I don't really understand what's going on. Anyway, now I "just" want to add a while-loop to ask for input until it is correct:
def inp_3():
while True:
s = raw_input(">>> ")
if s == '1':
return s
else:
print "wrong"
The test for inp_3 I thought would be the same as for inp_2 . At least I am not getting error messages. But the output is the following:
$ nosetests
......
# <- Here I press ENTER to provoke a reaction
# Nothing is happening though.
^C # <- Keyboard interrupt (is this the correct word for it?)
----------------------------------------------------------------------
Ran 7 tests in 5.464s
OK
$
The other 7 tests are sth. else (and ok).
The test for inp_3 would be test nr. 8.
The time is just the times passed until I press CTRL-C.
I don't understand why I don't get error- or "test failed"-meassages but just an "ok".
So beside the fact that you may be able to point out bad syntax and other things that can be improved (I really would appreciate it, if you would do this), my question is:
How can I test and abort while-loops with nosetest?
So, the problem here is when you call inp_3 in test for second time, while mocking raw_input with Mock(return_value="foo"). Your inp_3 function runs infinite loop (while True) , and you're not interrupting it in any way except for if s == '1' condition. So with Mock(return_value="foo") that condition is never satisfied, and you loop keeps running until you interrupt it with outer means (Ctrl + C in your example). If it's intentional behavior, then How to limit execution time of a function call in Python will help you to limit execution time of inp_3 in test. However, in cases of input like in your example, developers often implement a limit to how many input attempts user have. You can do it with using variable to count attempts and when it reaches max, loop should be stopped.
def inp_3():
max_attempts = 5
attempts = 0
while True:
s = raw_input(">>> ")
attempts += 1 # this is equal to "attempts = attempts + 1"
if s == '1':
return s
else:
print "wrong"
if attempts == max_attempts:
print "Max attempts used, stopping."
break # this is used to stop loop execution
# and go to next instruction after loop block
print "Stopped."
Also, to learn python I can recommend book "Learning Python" by Mark Lutz. It greatly explains basics of python.
UPDATE:
I couldn't find a way to mock python's True (or a builtin.True) (and yea, that sounds a bit crazy), looks like python didn't (and won't) allow me to do this. However, to achieve exactly what you desire, to run infinite loop once, you can use a little hack.
Define a function to return True
def true_func():
return True
, use it in while loop
while true_func():
and then mock it in test with such logic:
def true_once():
yield True
yield False
class MockTrueFunc(object):
def __init__(self):
self.gen = true_once()
def __call__(self):
return self.gen.next()
Then in test:
true_func = MockTrueFunc()
With this your loop will run only once. However, this construction uses a few advanced python tricks, like generators, "__" methods etc. So use it carefully.
But anyway, generally infinite loops considered to be bad design solutions. Better to not getting used to it :).
It's always important to remind me that infinite loops are bad. So thank you for that and even more so for the short example how to make it better. I will do that whenever possible.
However, in the actual program the infinite loop is how I'd like to do it this time. The code here is just the simplified problem.
I very much appreciate your idea with the modified "true function". I never would have thought about that and thus I learned a new "method" how tackle programming problems :) .
It is still not the way I would like to do it this time, but this was the so important clue I needed to solve my problem with existing methods. I never would have thought about returning a different value the 2nd time I call the same method. It's so simple and brilliant it's astonishing me :).
The mock-module has some features that allows a different value to be returned each time the mocked method is called - side effect .
side_effect can also be set to […] an iterable.
[when] your mock is going to be
called several times, and you want each call to return a different
value. When you set side_effect to an iterable every call to the mock
returns the next value from the iterable:
The while-loop HAS an "exit" (is this the correct term for it?). It just needs the '1' as input. I will use this to exit the loop.
def test_inp_3():
# Test if input is correct
__builtin__.raw_input = Mock(return_value="1")
assert_equal(inp_1(), '1')
# Test if output is correct if input is correct two times.
# The third time the input is corrct to exit the loop.
__builtin__.raw_input = Mock(side_effect=['foo', 'bar', '1'])
out = StringIO()
sys.stdout = out
inp_3()
output = out.getvalue().strip()
# Make sure to compare as many times as the loop
# is "used".
assert_equal(output, 'wrong\nwrong')
Now the test runs and returns "ok" or an error e.g. if the first input already exits the loop.
Thank you very much again for the help. That made my day :)