git.net

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

How can i stop this Infinite While Loop - Python


TLDR; declare if homework; doing someone's homework doesn't really help; 
Python is not ALGOL/Pascal/C/C++ by any other name; Python assignments 
should promote learning semantics as well as syntax; sometimes 
re-stating the problem leads to an alternate/better solution.


On 31/10/19 12:55 AM, ferzan saglam wrote:
> I have tried many ways to stop the infinite loop but my program doesn't seem to stop after 10 items! It keeps going...!)
> 
> ---------------------------
> total = 0
> while True:
> 
>    print('Cost of item')
>    item = input()
> 
>    if item != -1:
>      total += int(item)
>    else:
>      break
> 
> print(total)
> ---------------------------


A critique of this thread, plus a suggested approach to a solution:-


1 the OP
This is a contrived coding problem. Is it part of a course? To establish 
an honest relationship with your list-colleagues, should you have 
declared it as 'homework'?

Remembering that no-one 'here' is paid to be helpful, did you politely 
respond with the clarification requested?
(see also later threads)

There is an interesting psychology that you will notice when working 
with other people who are happy to be helpful (per this list-community); 
that if one stops to think about *how* to pose a question, sometimes the 
answer 'appears' - a burst of inspiration in your mind.

That can be difficult to remember if you've been struggling with a 
problem for hours with the resultant level of frustration.

At least the title of the post: "How can i stop this Infinite While 
Loop" is descriptive. Compared with some first-time poster's titles, 
this is clear and competent. Thanks!

Thinking about it though, is there a hint of the nature of the problem, 
or even then an answer, in there? ie pausing to think about it, is the 
problem actually the "stop" (as emphasised) or might it be the "while"? 
(more below)


2 respondents
This was an 'easy answer' question, so "well done" and "thank you" for 
jumping-in with the intention of contributing something to the community 
- quite possibly a first post for some. I encourage you to participate 
and do NOT wish to criticise you for having the best of motivations.

However, it is always a good idea to consider not only "the question", 
as asked, but to 'first ask why?' (which happens to (almost) be the 
title of a thoroughly-recommendable book for managers, 
potential-managers, and certainly coaches/mentors to read). You can see 
this in one respondent's <<<From what I understand you want to give the 
user the possibility to try 10 times or enter -1 to end the script, 
right?>>>

If (and this is *my* assumption!), the OP is a student attempting to 
learn Python, cf an experienced pythonista; giving "the answer" is NOT 
as helpful as it might seem. That's why the "pseudo code" solution was 
'better' than a Python equivalent.

What should the OP learn? Given 'the answer', would the OP be able to 
solve a similar problem when next encountered?

If the OP's learning-objective is 'Python', then the pseudo-code helped 
clarify the necessary thinking, without detracting from the OP's 
learning-opportunity. (cf an algorithms course)

In fact, and quite coincidentally, the best learning-opportunity here, 
has probably been the "off by one" experience - which the OP did indeed 
learn for himself. (Well done!)


3 the question itself/the questioner
The way the OP has attempted to solve this contrived-problem indicates a 
fundamental lack of understanding of the way Python works and/or the way 
pythonista think. However, the way the question has been posed indicates 
much the same! It smacks of an old, even ancient, ComSc problem; 
previously applied to other languages (something I might have written 
when learning/teaching FORTRAN more than four decades ago, for example). 
How does this coding-problem contribute to the *Python* learning 
process? (as well as contributing towards the learning ComSc principles, 
eg managing/terminating loops)


Thus:

> The output I am aiming for is for the code to stop asking 'Cost of item' after 10 inputs or until -1 is typed, but the code repeats itself on an infinite loop. I cannot seem to stop the infinite loop.

expresses the problem, but in the manner of other languages. The focus 
has been put on the "-1" fact - how to "stop". (remember the OP's title!)

Question: since we no longer present data as decks of punched-cards, 
what is today's more usual way to indicate EOF/EOD? ("end of file", "end 
of data") Is the minus-one "flag" a very good approach, or even 
particularly representative of work-place 'realities'?


Towards a solution:

OK, let's not argue the point - it's certainly beyond the OP's control, 
so we must consider it a "specification"...

The advice for solving ComSc (and other) problems is always to 'break 
down the larger problem into smaller, sub-problems and solve them' 
(which may, in-turn, involve breaking the sub-problems into smaller...)

Here 'the problem' may decompose into:
1 accept input value
2 accumulate (total) input data-values
3 count number of input data-values
4 terminate if have received ten data-values
5 decide if EOD/-1
6 display the total
(warning - or is it a ComSc learning-opportunity? understand that (5) is 
NOT a data-value for the purposes of (2), (3), and/or (6)! )


An excellent piece of advice (seen earlier in this thread) is to use the 
Python REPR to formulate answers and test ideas - one line of code at a 
time. (OP: you could have made your life easier by applying that advice 
BEFORE posing more recent questions)

First ensure the 'straight-line' is understood, coded, and tested. 
Sub-problems 1, 2, and 5 are (hopefully) quickly solved AND proven! 
(although accumulators/__iadd__/in-place operators) are also important 
ComSc and Python concepts to learn, in-time!)

There's little point in looking at (3) without a loop. So let's defer that.

The attempted solution says: start with a never-ending loop. 
Curiously-enough this seems exactly where the OP ran into problems:  "I 
cannot seem to stop the infinite loop." Question: why start one in the 
first place?

To avoid this problem, before starting something/anything, decide how 
it's going to end! (see also: signing cloud-computing contracts...) This 
loop has two termination-conditions: (4) ten data-values entered, as an 
"absolute maximum", and (5) the -1 flag, which may/not occur.

Consider them separately. The OP had the right idea of an if-construct 
checking for the flag and breaking the loop. We could have coded that in 
the REPR and tested it very quickly. However, this is a 
variable-situation. The -1 flag could take the place of the very first 
data-item, it could appear instead of any other of the ten acceptable 
data-items, or it might not appear at all!

Compare this with (4). The maximum is an absolute condition. The 
client-requirement doesn't seem to care how large or how small the total 
might be. The routine must stop accumulating data after the tenth item. 
No discussion! What happens/how does 'the picture' change if make this 
our 'primary' condition, ie code this first, and then worry about (5) 
later?

Which leads to a learning-opportunity in Python: which Python construct 
is designed to manage a loop for a fixed number of repetitions?

The next step in the REPR then, is to code a for-loop which repeats 10 
times*. Hint: you don't need to include the solutions for (1), (2), and 
(5) within this test, print something ("hello world!" perhaps?) but 
test/ensure it happens ten times! This is an opportunity to read-up 
about Python's range(), which will also lead towards solving sub-problem 3!

Now, we can worry about the variable termination (sub-problem 5), 
applying the same technique as employed in the OP's existing code 
("break"). Thus, the -1-termination has become trivial, instead of being 
the major trial and headache that it was, leading up to this post.

Which leaves us with (2), which was solved earlier in this conversation 
- and can be easily proven in the REPR. That said, experimenting with 
the REPR would quickly provide a learning-opportunity by illustrating 
the issue/error of data-items being read ("input") as strings, and 
needing to be converted to integer before performing any arithmetic.

The value of Python's REPR *cannot* be under-stated, particularly to 
beginners - but when facing something for the first time, aren't we all 
'beginners'?


* sadly, we're back to critique nr3. Counting incidents and specifically 
the "off by one" bug, discovered here serendipitously, are amongst the 
most frequent, if not THE most frequent, errors found in code (using 
almost any common programming language) and dating right back to the 
aforementioned FORTRAN and beyond to the beginnings with Assemblers and 
machine language code!

Python has a wonderful philosophy, that its "for" loop is NOT a means of 
counting repetitions from 'here' to 'there' eg zero?one to 10. It is a 
superior (IMHO) piece of language-design: a for-each construct. It is 
nicely illustrated as: for each element in a list, do 'something'.

Accordingly, this perhaps-venerable ComSc problem is not helpful when 
learning Python, even if Python will (happily) solve said problem!


WebRefs:
https://simonsinek.com/product/start-with-why/
https://en.wikipedia.org/wiki/Functional_decomposition
https://en.wikipedia.org/wiki/Eureka
https://docs.python.org/3/reference/compound_stmts.html
https://docs.python.org/3/library/operator.html
-- 
Regards =dn