[Courses] [python] Lesson 6: Functions and dictionaries
Akkana Peck
akkana at shallowsky.com
Wed Jul 27 04:11:44 UTC 2011
(Sorry for the delay -- I was traveling yesterday and getting caught
up today.)
lenore borisova writes:
> I just wanted to submit a revision to mine - this revises problem 3 in
> Homework 6.
Nice! Also a great choice of flashcard topics -- I'm having fun
running yours and seeing how many I get right, and it's easy to
tell whether the answers are right or not -- no ambiguity, once you've
done strip() and lower().
> I had one issue, where my dictionary contained 9 elements, but I could only
> get it to go through 8 of them before there was an IndexError so that's why
> I did the len(elements)==1 because I couldn't think of a way around that.
> The problem came in when I was trying to delete an element from the
> dictionary if the question had already been asked so that it wouldn't mess
> up the correct/incorrect count at the end. After a question was asked, it
> would loop and then ask another random question from the dictionary. I did
> want it to go through all items in the dictionary. I had one-word answers so
> for matching all I needed to do was make sure the case was consistent.
>
> So, this revision now adds a condition to test if there are no elements (or
> an empty dictionary) - if it is empty, it just breaks the loop and ends the
> program, displaying the final count. If it's not empty, it continues to loop
> and randomly get a question/answer from the dictionary.
That works fine, and there's nothing wrong with it. But here's a way
you could structure it and make the code a little shorter, and maybe
cleaner (that's always a judgement call):
First, you call (symbol, answer) = chem(elements) once before you
start the loop, then again at the end of the loop each time through.
Sometimes you have to do that, but any time you find yourself typing
the same line more than once, think about whether you could do
things differently. In this case, you could put that line,
(symbol, answer) = chem(elements)
as the first step inside the loop, instead of calling it first then
at the end.
If you do that, so you know the first thing you'll do inside the
loop is to choose something from elements, then you can change
while True:
to
while len(elements) > 0:
But actually you could even shorten that a little: in Python, if you
do a conditional test (if or while) on a list or dictionary that's
empty, Python will treat it as False. So you could also say:
while elements:
If you do that, then you don't need the clause:
if len(elements) == 0:
ui()
counts()
ui()
break
You can get rid of the if len() test since you're using that for
your while loop, and you can move the rest outside the loop and get
rid of the break. So you'd have the last few statements in your
loop, then the summing-up stuff outside the loop, like this:
del elements[symbol]
total += 1
ui()
counts()
ui()
It makes it a little shorter and (I think) a little cleaner.
If you get into the "shorter and cleaner" thing, there's one other
shortcut you could take that a lot of programmers like:
if maybe == "q":
# do summing-up stuff here
break
else:
if maybe == answer:
...more stuff
In a case like that, where you're starting with a short clause that
tests whether it's time to break out of the loop, you know that
if maybe == "q" then you're definitely going to be out of the loop
after the break. So you don't actually need the else; you could say
if maybe == "q":
# do summing-up stuff here
break
if maybe == answer:
...more stuff
The advantage of this is that now the whole rest of your loop is
less indented than it was, and maybe a little easier to read. But
in some cases you might think it's less clear if you don't have the
else. So don't feel like you have to do it that way -- it's still
perfectly valid to say if (condition) break else -- but omitting
the else is an option, and you'll see a lot of people structure code
that way (including me).
Long answer -- hope that was all clear!
...Akkana
More information about the Courses
mailing list