Skip to content

Catching up

December 11, 2009

Hi again!  After too long a hiatus, I’m back to coding and blogging.  I’ve spent the last couple of weeks fighting with a pygame install (it turns out that because bdist_mpgk and setuptools haven’t been ported yet, there’s no Mac OS installer available for Python 3.1 and we need to build it from source—oh joy). I’m just about at the point where I’m ready to skip that chapter because I miss making progress and the exercise just isn’t worth the frustration anymore.  But I do hope to circle back to it at some point.  In the meantime, I thought I’d catch you up on Chapter 6…

Chapter 6 sees us writing a point-of-sale (POS*) program for a health club and/or its attached coffee shop.

*[Yes: my brain, too, does a double-take at that abbreviation throughout the chapter. Why, I wonder at first, am I being encouraged to write crappy code? English is great.]

At first, our task was simple: we needed to collect information for each order comprising the customer’s credit card number, the item’s price (without a decimal point) and a brief item description.  We used this formatted string to collect the information (which then got appended to a text file):

“%16s%07d%16s\n” % (credit_card, price*100, description)

Okay, no problem.  We’ve allotted the standard 16 digits for the credit card, 7 digits padded out with 0s for the price (that way we can charge up to $99,999.99 for our merchandise; heckuva coffee shop, Brownie), and we have 16 characters for our item description.

Naturally, by the time we got around to running the program and providing input, I had to try to break the thing.  First, I played nice.  I ordered a latte and cashier me entered my credit card number as 1234567890123456.  The text file showed:

12345678901234560000200           LATTE

Fine.  But then I was hungry.  So I ordered a muffin, but cashier me must have accidentally hit an extra key because 17 digits were entered.  I ran over to my text file, expecting it to have truncated the entry.  But no, I got:

123456789012345670000120          MUFFIN

Ooo, so the format doesn’t provide an upper-bound for the entry.  Good to know.  But my understanding is it provides a lower-bound; let’s test that.  More caffeine, please, with a 10-digit card number:

12345678900000200           LATTE

Right, this is what I expected.  If I’d coded “%016s%07d%16s\n” % (credit_card, price*100, description) then it would have filled in leading 0′s.  Good.  Okay, what happens when I throw it a curveball in the form of some irreverently arranged letters in there with the numbers?  Turns out, it will spit out what you put in:

kick me0000150           DONUT

Nice.  But I suppose that makes sense, since I told it to expect a string.  What if I tell it to expect a number?  Let’s try modifying the string format to:

“%16d%07d%16s\n” % (credit_card, price*100, description)

Now it should expect a number, right?  And indeed, when the sassy cashier me inputs another erroneous card entry, I get a TypeError:

1. DONUT
2. LATTE
3. FILTER
4. MUFFIN
5. Quit
Choose an option: 2
Credit card number: kick me
Traceback (most recent call last):
File “/Users/xfer/Desktop/Python/pos.py”, line 19, in <module>
save_transaction(prices[choice - 1], credit_card, items[choice - 1])
File “/Users/xfer/Desktop/Python/transactions.py”, line 3, in save_transaction
file.write(“%16d%07d%16s\n” % (credit_card, price*100, description))
TypeError: %d format: a number is required, not str

Interesting.  Okay, let’s make sure it works when I play nice.  Whoops!  Another TypeError!  I’m not entirely sure why this happened, so if anyone has any insight, please do tell.

The rest of the chapter progressed fairly smoothly.  We learned how to separate functions we’d written into modules we could call, so that they could be used in multiple locations and remain consistent across updates and multiple uses.

Tangentially, we learned how to comment our code, which is always a good thing.

Finally, we learned how to apply a discount or two to our prices—via another module—and the importance of qualifying function names.  We used a standard discount that applied to all customers because of a limited-time promotion, and a conditional discount that applied only to customers with a “club card” of sorts.  Both of these functions were called “discount”, so we needed to use FQNs to distinguish them in the code.  Seems pretty straightforward.

Onward and upward!

About these ads
10 Comments leave one →
  1. December 14, 2009 9:08 am

    Great to see you back in action, Julie. Re: getting PyGame to work on Mac OS X. I know David got it to work … also, I have recently acquired a new MacBook and already have Python 3.1 installed and I’m just about to have a go at getting PyGame up-and-running, too. I plan to make detailed notes on what I do so that I can update the book’s support website with the steps required. I’ll cross-link to this blog when I’m done, as it’s not just Chapter 7 that needs PyGame. (I know that this may not help you, but: users of Windows and Linux will have little or no difficulty getting PyGame to work). So, stay tuned … I’ll have my notes online by the end of this week. –Paul.

  2. John permalink
    December 17, 2009 3:55 am

    I’m using a hackintosh and just started chapter 7, so I will see if I have the same issues as you with pygame. I’d prefer not to do it in windows:) As to your error, I think (and I’m just guessing) that you would need something like:

    int(credit_card)

    in that line or before it is sent to the function. I’ve gotten these errors trying to come up with the code before seeing the answer and it was usually solved with a str() or int(). Hope that helps. Like your blog!

    • December 18, 2009 8:29 am

      You entered “kick me” as the credit card number, when the program is designed to take what you entered and use it as a number later on (in the %d bit). At that point, the “kick me” string can’t be converted to a number (as it isn’t one) and the program fails with a TypeError – the program wanted a number, you gave it a string, and now it’s just confused. There are mechanisms that you can use to ensure you get the type of something right before you use it (and to recover – and keep going – when a TypeError does happen), but we don’t really cover that until Chapter 8.5 with Exception Handling.

      Your point about POS (point-of-sale) abbreviations is well made. What can I say … use computing-types just love our acronyms! Of course, there are lots of these in “regular life” to: FYI, ASAP, BTW, and so on.

      • December 18, 2009 8:31 am

        Oh man … That should read “us” computing-types (not “use”) and “too” not “to”. Jeez … where’s my editor when I need him?!? ;-)

  3. December 17, 2009 2:18 pm

    Here are the instructions for getting PyGame to install and run on Mac OS X. Find them as a PDF at the bottom of this page: http://programming.itcarlow.ie/pygame.html – let me know if these work for you (or not). Cheers, Paul.

    • Kevin permalink
      December 22, 2009 3:27 pm

      Considering buying the book, and owning a Mac, I’d sure like to know how the PyGame install works out for other people.

    • December 22, 2009 5:31 pm

      Thanks Paul! I haven’t upgraded to Snow Leopard yet, so I’m still running 10.5.8 — some of the commands seem to be different, so I haven’t got it quite all working yet, but your PDF is an enormous help.

      • December 23, 2009 9:03 am

        You’re welcome, Julie. Step 6 for 10.5.8 may need to be written as: “export CC=’/usr/bin/gcc-4.0′ CFLAGS=’-isysroot /Developer/SDKs/MacOSX10.5.sdk -arch i386″ .. I say “may” as I don’t have anything older than 10.6 to test on. Good luck with your install (I’m pretty sure David got PyGame to work on his 10.5). –Paul.

  4. January 10, 2010 7:59 pm

    Crumbs guys. Though I’m not looking forward to fighting with my macbook to install pygame, I think I’ll find it easier with your instructions
    Thanks!

  5. February 10, 2010 7:17 pm

    Julie, I believe your program blew up with the %16d format code because even though you entered digits for the credit card number, “credit_card” was still a string. The %d format code expects a numeric data type, not a string containing numeric digits. In the example below, “x = 10″ assigns an integer to x, and that works. However, “x = ’10′” assigns a string to x containing the digits 1 and 0, and that does not work with the %d format code.

    >>> x = 10
    >>> print “%5d” % x
    10
    >>> x = ’10′
    >>> print “%5d” % x
    Traceback (most recent call last):
    File “”, line 1, in
    TypeError: %d format: a number is required, not str
    >>>

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: