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:
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:
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:
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. DONUT2. LATTE3. FILTER4. MUFFIN5. QuitChoose an option: 2Credit card number: kick meTraceback (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_transactionfile.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!