473,659 Members | 2,671 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Struggling with basics

A week ago I posted a simple little hi-score routine that I was using to
learn Python.

I've only just managed to examine the code, and the responses that
people gave, and I'm now seriously struggling to understand why things
aren't working correctly.

At present my code is as follows...

import random
import bisect

class HiScores:
def __init__(self,h iScores):
self.hiScores=[entry for entry in hiScores]

def showScores(self ):
for score,name in self.hiScores:
score=str(score ).zfill(5)
print "%s - %s" % name,score
def addScore(self,s core,name):
score.zfill(5)
bisect.insort(s elf.hiScores,(s core,name))
if len(self.hiScor es)==6:
self.hiScores.p op()

def lastScore(self) :
return self.hiScores[-1][0]

def main():

hiScores=[('10000','Alpha '),('07500','Be ta'),('05000',' Gamma'),('02500 ','Delta'),('00 000','Epsilon')]

a=HiScores(hiSc ores)
print "Original Scores\n---------------"
a.showScores()

while 1:
newScore=str(ra ndom.randint(0, 10000))
if newScore > a.lastScore():
print "Congratulation s, you scored %s " % newScore
name=raw_input( "Please enter your name :")
a.addScore(newS core,name)
a.showScores()

if __name__=="__ma in__":
main()
My first problem (lack of understanding of course) is that if I run the
above, I get an error saying:

print "%s - %s" % name,score
TypeError: not enough arguments for format string

Now I understand what it's saying, but I don't understand why.

If I change the code to read:

print "%s - %n" % name, score (thinking of course that ah-ha, score is
numeric) then I get the same error.

The only way for the program to run is to simply have

print name,score (or print score,name)
The final part that's simply not working correctly is that the entire
program isn't sorting the data.

If I run the program and get a score of, say, 6789, then when I add my
name, nothing is entered. I have changed the clause that deletes (pops)
the last array if the array count is 6 and seen what figures are being
entered into the array.

Sure enough they are going in the array, and they are being sorted, but
they are only being sorted AFTER the 00000 of the initial array creation.

I'm pretty sure it's to do with comparing a string against an integer
but can't for the life of me see where to force the comparrison to check
against two integers.

Apologies for going over old ground and if I'm not understanding, I'm
getting there honest ;)

Sep 25 '05 #1
8 1409
Jason wrote:
A week ago I posted a simple little hi-score routine that I was using to
learn Python.

I've only just managed to examine the code, and the responses that
people gave, and I'm now seriously struggling to understand why things
aren't working correctly.

At present my code is as follows...

import random
import bisect

class HiScores:
def __init__(self,h iScores):
self.hiScores=[entry for entry in hiScores]

def showScores(self ):
for score,name in self.hiScores:
score=str(score ).zfill(5)
print "%s - %s" % name,score
def addScore(self,s core,name):
score.zfill(5)
bisect.insort(s elf.hiScores,(s core,name))
if len(self.hiScor es)==6:
self.hiScores.p op()

def lastScore(self) :
return self.hiScores[-1][0]

def main():

hiScores=[('10000','Alpha '),('07500','Be ta'),('05000',' Gamma'),('02500 ','Delta'),('00 000','Epsilon')]

a=HiScores(hiSc ores)
print "Original Scores\n---------------"
a.showScores()

while 1:
newScore=str(ra ndom.randint(0, 10000))
if newScore > a.lastScore():
print "Congratulation s, you scored %s " % newScore
name=raw_input( "Please enter your name :")
a.addScore(newS core,name)
a.showScores()

if __name__=="__ma in__":
main()
My first problem (lack of understanding of course) is that if I run the
above, I get an error saying:

print "%s - %s" % name,score
TypeError: not enough arguments for format string

Now I understand what it's saying, but I don't understand why.
The '%' operator expects a tuple or a single value on its right. So you
have to set parentheses around "name, score".

That needs getting used to, but otherwise it can't be discerned from
print ("%s - %s" % name), (score).
If I change the code to read:

print "%s - %n" % name, score (thinking of course that ah-ha, score is
numeric) then I get the same error.
For integers you can use %s or %i (or %d), see http://docs.python.org/lib/typesseq-strings.html.
Apologies for going over old ground and if I'm not understanding, I'm
getting there honest ;)


No problem. c.l.py is newbie-friendly.

Reinhold
Sep 25 '05 #2
Jason wrote:
My first problem (lack of understanding of course) is that if I run the
above, I get an error saying:

print "%s - %s" % name,score
TypeError: not enough arguments for format string

Now I understand what it's saying, but I don't understand why.


The problem is precedence.

print "%s - %s" % name,score

is equivalent to:

print ("%s - %s" % name),score

not:

print "%s - %s" % (name,score)

The % operator binds more tightly than the comma, so you need to put
parentheses around the argument to % (as in the last line above).
Sep 25 '05 #3
On Sun, 25 Sep 2005 19:37:32 +0100, Jason <ja***@jasonmhi rst.co.uk>
declaimed the following in comp.lang.pytho n:

My first problem (lack of understanding of course) is that if I run the
above, I get an error saying:

print "%s - %s" % name,score
TypeError: not enough arguments for format string
print "%s - %s" % (name, score)

You need to pass a two-element tuple to the % operator; without the
parens you have the equivalent of two print statements:

print "%s - %s" % name, # the comma says "don't go to new line"
print score

I'm pretty sure it's to do with comparing a string against an integer
but can't for the life of me see where to force the comparrison to check
against two integers.
Look closely:
1) You initialize the high-score table with zero-filled STRINGS
2) show() is also taking the entry from the table, converting to STRING
(which is redundant for a string data item), and then zero-filling it
(also redundant at this point)
3) add() is taking a value, presumed to be a string, zero-filling it,
and then... THROWS AWAY the zero-filled version and saves the original
non-zero-filled.
4) bisect requires a sorted list -- but your list doesn't really count
as sorted; you have a REVERSE sorted list. bisect puts larger values
AFTER smaller ones.

Here's a DIFF report between your code, and what I did to it... If
you aren't familiar with the notation...

m1,m2cn1,n2 old file lines m1 to m2 CHANGE new file lines n1 to n2
< text old file contents text new file contents
m1an1,n2 old file lines m1 APPEND after new file n1 to n2

m1,m2dn1? old file lines m1 to m2 DELETE (? showing new file line just
above?)[not used in this diff]

9,12c9,11
< def showScores(self ):
< for score,name in self.hiScores:
< score=str(score ).zfill(5)
< print "%s - %s" % name,score
--- def showScores(self ):
for i in range(len(self. hiScores)-1, -1, -1):
print "%s - %s" % self.hiScores[i] 16c15
< score.zfill(5)
--- score = score.zfill(5) 19c18
< self.hiScores.p op()
--- self.hiScores.p op(0)
I think the next one is a problem of wrap-around caused by having no
spaces in the line... they need to be indented properly...
26c25
<
hiScores=[('10000','Alpha '),('07500','Be ta'),('05000',' Gamma'),('02500 ','Delta'),('00 000','Epsilon')]
--- hiScores=[('10000','Alpha '),('07500','Be ta'),('05000',' Gamma'),('02500 ','Delta'),('00 000','Epsilon')] 27a27,28 hiScores.revers e()
-- =============== =============== =============== =============== == <
wl*****@ix.netc om.com | Wulfraed Dennis Lee Bieber KD6MOG <
wu******@dm.net | Bestiaria Support Staff <
=============== =============== =============== =============== == <
Home Page: <http://www.dm.net/~wulfraed/> <
Overflow Page: <http://wlfraed.home.ne tcom.com/> <

Sep 25 '05 #4
Duncan Booth wrote:
Jason wrote:
My first problem (lack of understanding of course) is that if I run the
above, I get an error saying:

print "%s - %s" % name,score
TypeError: not enough arguments for format string

Now I understand what it's saying, but I don't understand why.


The problem is precedence.

print "%s - %s" % name,score

is equivalent to:

print ("%s - %s" % name),score

not:

print "%s - %s" % (name,score)

The % operator binds more tightly than the comma, so you need to put
parentheses around the argument to % (as in the last line above).

Well said. :)

- Peter
Sep 25 '05 #5
On Sun, 25 Sep 2005, Jason wrote:
A week ago I posted a simple little hi-score routine that I was using to
learn Python.

I've only just managed to examine the code, and the responses that people
gave, and I'm now seriously struggling to understand why things aren't
working correctly.
Others have dealt with the string printing problem, so i'll leave that.

The problem with the sorting is that you're not consistent about how
scores are represented - are they strings or integers? At present, you
sometimes use one and sometimes the other, with the result that the sort
basically pukes all over you. To fix this, pick one type (hint: integers),
and use that consistently. I'll show you how to do that below (although
it's not exactly hard).

Oh, and i'm a picky git, so i'm going to point out some other flaws in the
code!
At present my code is as follows...

import random
import bisect

class HiScores:
def __init__(self,h iScores):
self.hiScores=[entry for entry in hiScores]
One bug and one wart here.

The wart is the way you initialise self.hiScores - you use a list
comprehension when you can just call the list builtin:

self.hiScores = list(hiScores)

The bug is that you don't sort the list. If you're certain that the
initial set of high scores will always come sorted, that's okay, but i'd
say it was good practice to sort them, just in case.

In fact, i'd punt the addition to addScore:

def __init__(self, hiScores):
self.hiScores = []
for score, name in hiScores:
self.addScore(s core, name)

This is the 'Once And Only Once' principle in action; the knowledge about
how to keep the list sorted is expressed once and only once, in addScore;
if any other parts of the code need to add items, they call that. This
means there's only one piece of code you have to check to make sure it's
going to get this right.
def showScores(self ):
for score,name in self.hiScores:
score=str(score ).zfill(5)
print "%s - %s" % name,score
As has been pointed out, you need to wrap parens round "name, score" to
make it into a tuple.

Apart from that, i'd skip the string interpolation and just write:

for score, name in self.hiScores:
print name, "-", str(score).zfil l(5)

If you insist on the string interpolation, i'd still elide the
intermediate variable and write:

for score, name in self.hiScores:
print "%s - %05i" % (name, score)

The %05i in the format string means 'an integer, zero-filled to five
digits'. Good, eh?
def addScore(self,s core,name):
score.zfill(5)
bisect.insort(s elf.hiScores,(s core,name))
if len(self.hiScor es)==6:
self.hiScores.p op()
Two problems there. Well, two and a half.

Firstly, the type confusion - are scores strings or integers? the zfill
indicates that you're thinking in terms of strings here. You should be
using integers, so you can just drop that line.

And if you were working with strings, the zfill would still be wrong (this
is the half problem!) - zfill doesn't affect the string it's called on
(strings are immutable), it makes a new zero-filled string and returns it.
You're not doing anything with the return value of that call, so the
zero-filled string would just evaporate into thin air.

Secondly, bisect.insort sorts the list so that the highest scores are at
the tail end of the list; list.pop takes things off that same end, so
you're popping the highest scores, not the lowest! You need to say pop(0)
to specify that the item should be popped off the head (ie the low end) of
the list.

Also, i'd be tempted to program defensively and change the test guarding
the pop to "while (len(self.hiSco res > 6):".

All in all, that makes my version:

def addScore(self, score, name):
bisect.insort(s elf.hiScores, (int(score), name))
while(len(self. hiScores) > 6):
self.hiScores.p op(0)
def lastScore(self) :
return self.hiScores[-1][0]
This will return the top score; you want self.hiScores[0][0].
def main():

hiScores=[('10000','Alpha '),('07500','Be ta'),('05000',' Gamma'),('02500 ','Delta'),('00 000','Epsilon')]
Here you've got scores as strings, and this is the root of the problem.
Change this to:

hiScores=[(10000,'Alpha') ,(7500,'Beta'), (5000,'Gamma'), (2500,'Delta'), (0,'Epsilon')]

Note that i've taken the leading zeroes off - leading zeroes on integers
in python are a magic signal that the number is octal (yes, base eight!),
which is not what you want at all.
a=HiScores(hiSc ores)
print "Original Scores\n---------------"
a.showScores()

while 1:
"while True:" is preferred here.
newScore=str(ra ndom.randint(0, 10000))
Take out the str().
if newScore > a.lastScore():
print "Congratulation s, you scored %s " % newScore
Make that a %i (or a %05i).
name=raw_input( "Please enter your name :")
a.addScore(newS core,name)
a.showScores()

if __name__=="__ma in__":
main()
Works like a charm!
The final part that's simply not working correctly is that the entire program
isn't sorting the data.

If I run the program and get a score of, say, 6789, then when I add my name,
nothing is entered. I have changed the clause that deletes (pops) the last
array if the array count is 6 and seen what figures are being entered into
the array.

Sure enough they are going in the array, and they are being sorted, but they
are only being sorted AFTER the 00000 of the initial array creation.

I'm pretty sure it's to do with comparing a string against an integer
but can't for the life of me see where to force the comparrison to check
against two integers.


Simple - you just make sure the scores are all integers in the first
place!

tom

--
double mashed, future mashed, millennium mashed; man it was mashed
Sep 25 '05 #6
Tom, best explanation yet! Entertaining as well as educational.

The "%05i" trick is very neat, must remember that one!

Everything working a charm apart from the viewScores is still returning
the results from the lowest score (at the top) to the highest score.

What I'd like to know is do you think it would be better to sort the
list in memory, or print it out sorted? If the latter, then naturally
I'd need to change the showScores section to show the list in a reverse
order. But, would sorting the list in memory be more effective?

Sep 25 '05 #7
"Jason" <ja***@jasonmhi rst.co.uk> wrote:
What I'd like to know is do you think it would be better to sort the
list in memory, or print it out sorted? If the latter, then naturally
I'd need to change the showScores section to show the list in a reverse
order. But, would sorting the list in memory be more effective?


The list *is* sorted; the thing is that it is in ascending order (from lowest to highest) but you
would rather have it in descending. There are (at least) two alternatives:

1. Keep the list as it is now in ascending order and print it in reverse. In python 2.4, this is as
elegant and efficient as it can, using the reversed() builtin function. Just replace in showScores
"for score,name in self.hiScores" with "for score,name in reversed(self.h iScores)". reversed()
returns an iterator over the sequence, not a new list, so the memory overhead is minimal.

2. Instead of storing (score,name) pairs, store (-score,name). When a list of the latter is in
ascending order, the former is in descending. In this case of course, you have to make sure that
showScores() and lastScore() return the actual (positive) score, not the stored (negative) one.

I would go for the first alternative but YMMV.

George
Sep 26 '05 #8
George Sakkis wrote:
"Jason" <ja***@jasonmhi rst.co.uk> wrote:
What I'd like to know is do you think it would be better to sort the
list in memory, or print it out sorted? If the latter, then naturally
I'd need to change the showScores section to show the list in a reverse
order. But, would sorting the list in memory be more effective?


The list *is* sorted; the thing is that it is in ascending order (from lowest to highest) but you
would rather have it in descending. There are (at least) two alternatives:

1. Keep the list as it is now in ascending order and print it in reverse. In python 2.4, this is as
elegant and efficient as it can, using the reversed() builtin function. Just replace in showScores
"for score,name in self.hiScores" with "for score,name in reversed(self.h iScores)". reversed()
returns an iterator over the sequence, not a new list, so the memory overhead is minimal.

2. Instead of storing (score,name) pairs, store (-score,name). When a list of the latter is in
ascending order, the former is in descending. In this case of course, you have to make sure that
showScores() and lastScore() return the actual (positive) score, not the stored (negative) one.

I would go for the first alternative but YMMV.

George

Thanks George, I've learned a lot tonight.

Sep 26 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
2002
by: Rowan | last post by:
Hi there, it's me again. I am having trouble with a view again. I am trying to do a calculation, but there are some checks that need to be taken into consideration. Maybe a view is not the right way to deal with this. I don't know. This is the beginning of my query. SELECT coalesce(f.filenumber, i.filenumber) as filenumber, i.InvoiceNumber, i.InvoiceValue, il.lineid, MPF = .21 * (il.UnitCost * il.UnitQty + il.AddMMV - il.MinusMMV -...
1
2274
by: manish | last post by:
Hi, I am a fresher in the programming field i.e although I have done programming at the basic level but at professional level I am very new and I am facing many problems. These probllems are not taughtand I am not getting any Refrences to cope with them. ********Setting in VC++ 6.0 I don'know to apply setting for various/different projects. I am not getting basics out of it .Can u pls tell me how to make a good understanding of...
11
22797
by: briankind | last post by:
Hello i have these radio buttons and i wish to have the corresponding textboxes to be visible when the radiobutton is selected. any Help? snippets. thanks thanks in adv Bry
0
3234
by: babu8880 | last post by:
www.convensysglobal.com/elearn You can login and attend courses and similar resources ask your doubts from experienced engineers in iphone and Objective C Domain You can attend live classes through our website with experienced teachers available world wide. Some among you can also be teachers while others will be your students. This is fun and adds knowledge in the domain of i-Phone Development. We request all users to be active in...
0
8339
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8751
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8535
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
7360
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5650
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4176
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4338
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
1982
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
2
1739
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.