Multiplying Strings

11 Oct, 2017

Robin L writes (excerpted):

I am trying to teach myself how to code and thought this was a good place to begin. I am having trouble with the "multiplying strings" section. I don't know anyone else who codes so I am hoping that you are still available at this email. This is the part about printing a letter in the shell. For some reason when I run mine the "print()" keeps actually printing "()".

Can you please help me figure out what I am doing wrong?

There's a pretty major difference between printing with older versions of Python (Python2.7 and earlier) and newer versions (Python3 and later). In Python2, print is a statement, which means this works fine:

print "hi there"

If you try that in Python3, you'll get an error:

print "hi there"
  File "<stdin>", line 1
    print "hi there"
               ^
SyntaxError: Missing parentheses in call to 'print'

That's because print in Python3 is a function not a statement.

Why does that make a difference? In Python2, this code...

print()

...is a print statement followed by an empty tuple. You're effectively telling Python to "print this empty tuple", and by quirk of the way the print statement works, you get (). The exact same code in Python3 is a function name (print) followed by an open bracket, no parameters, and a closing bracket. You're providing no parameters and the function prints nothing as a consequence. And that, basically, is the difference.

Cutting a long story short - all you're doing wrong is running an older version of Python. Check chapter one, and follow the instructions to install Python3, and the code will work as you expect.


Stickman Refusing To Move

17 Jul, 2017

Haran R writes:

I tried out the code for the two games and have successfully run the first game (bounce). The second game however did not run like how i wished it to. I followed the book’s instructions to the letter, used the GIMP software to create the images, saved it in a directory and saved the code in the same directory. The graphics came out fine but unfortunately I have not been able to get the stickman to move. I have followed the coding in the book to the letter and have checked my code against the coding in the book multiple times and i can see no mistakes.

The problem is with the indentation in your Stick Man class. If you look at the indentation of your code...

indentation 1

and then compare with mine...

indentation 2

...hopefully you'll see where you've gone wrong (if it's not immediately obvious, take a look at the vertical line coming down from the animate function in each of the code samples, and you'll see where the indentation isn't right). When I fixed the indentation on your code, it worked perfectly -- so you were almost there.

Hope that helps.


Tcl Error

12 May, 2017

丁明 writes (edited for spelling):

In your book <<python for kids>> chapter 13, when I run the program, the python shell has a error I can't understand. my python version 3.6.0. Thank you for your reply!!

error.png

I'm not sure if the Chinese edition has captured the text on page 199 of the English version of the book:

You may see error messages written to the shell when you close the game window. This is because when you close the window, the code is breaking out of the while loop, and Python is complaining about it.

The is exactly the error you are seeing when you run that code and then close the window. You are stopping (interrupting) Python while it is running the code, and an error message is displayed as a consequence.

Basically, you can ignore the message, but if you want to know how to get rid of it for good, one option is to replace the loop at the bottom:

while True:
    ball.draw()
    tk.update_idletasks()
    tk.update()
    time.sleep(0.01)

...with this...

try:
	while True:
	    ball.draw()
	    tk.update_idletasks()
	    tk.update()
	    time.sleep(0.01)
except TclError:
	pass

You can find more about error handling here: https://wiki.python.org/moin/HandlingExceptions


Windows 10

09 Apr, 2017

I've come across some uncorroborated reports that some of the instructions, or examples, in Python for Kids don't work with Windows 10. Uncorroborated because it's unfortunately nothing more than "it don't work". Not spectacularly useful, so I've finally gotten around to installing Windows 10 in VirtualBox to test this out.

Instructions for Python installation remain pretty much the same, except that the latest version of Python is now 3.6, whereas on the last printing of PfK, it was 3.5. The results of installation aren't too dissimilar to Windows 7 either:

windows-10 start menu (small image)

I cherry-picked a few of the code samples at the beginning of the book to test, but wasn't expecting any of those to be a problem (they weren't), and then went through the more complicated code (turtle, tkinter) in the rest. Everything works as expected, except there is a little bit of graphical weirdness in the Bounce game (chapters 13, 14) where the ball seems to deform as it moves. I'm pretty certain this is an artifact of using Windows inside VirtualBox (I've never found animated graphics to work particularly well when you're in an OS inside an OS) - it's certainly not a problem in Linux or on a Mac. But interested to hear if anyone else has experienced the same issue on Windows:

Deformed ball


That's pants!

06 Apr, 2017

Lee writes:

I'm not fully understanding the HugeHairyPants program on pages 72-73 of Python For Kids. I initially thought that the loop would produce "huge huge hairy hairy pants pants," reasoning that the program would assign the first value to i, then the identical value to j, and continue the loop. So why is the variable j assigned all of the values? My thought was that the program commands i to be the first variable ('huge'), then stops there because the variable j is introduced next. Since there is no other variables after j, it then gets assigned every variable. Is this correct? (It doesn't sound right to me, though.)

So let's break the code down a bit more then. Here's the list...

hugehairypants = ['huge', 'hairy', 'pants']

...and then the first two lines of the loop code:

for i in hugehairypants:
	print(i)

If we run this code right now we get:

huge
hairy
pants

Each time the value in i is (effectively) replaced with the next value in the list (it's actually not quite as simple as that, but it can be easier to think of it that way when you start programming).

It's important to remember that every time we loop here, we're executing all the statements in the block of code - that's the indented part. And that's why if we look at the original example...

for i in hugehairypants:
	print(i)
	for j in hugehairypants:
		print(j)

...it first executes print(i), then it executes the second for-loop - that's looping over the hugehairypants list again, calling print(j) three times, then back to print(i) again, and so on. If we just look at the print statements Python is executing in these two loops, this is what it looks like:

print(i) # first for-loop - the value in i is now 'huge'
print(j) # second for-loop - the value in j is now 'huge'
print(j) # second for-loop - the value in j is now 'hairy'
print(j) # second for-loop - the value in j is now 'pants'
print(i) # first for-loop - the value in i is now 'hairy'
print(j) # second for-loop - the value in j is now 'huge'
print(j) # second for-loop - the value in j is now 'hairy'
print(j) # second for-loop - the value in j is now 'pants'
print(i) # first for-loop - the value in i is now 'pants'
print(j) # second for-loop - the value in j is now 'huge'
print(j) # second for-loop - the value in j is now 'hairy'
print(j) # second for-loop - the value in j is now 'pants'

If you need something more visual, I suggest drawing two rectangles on a piece of paper with 3 cells. Write the 3 values from the list in the cells (obviously it's not really two lists, but easier this way). Get two small coins; the first coin marks the value in i, the second coin marks the value in j. Work through the code as though you were running it yourself - move each coin to show how the value changes as we loop:

Visual guide


Epic Amazon Fail

22 Mar, 2017

Frankly this is bizarre, but if you're looking for Python for Kids, I suggest you don't buy on Amazon for the moment:

Expensive!! (small image)

Much as I'd like to be getting a cut of that price, I somehow doubt I'm getting anything -- and you're possibly getting a poor quality knock off, going by this:

https://twitter.com/billpollock/status/844030960333152256

(Some more discussion on Hacker News here: https://news.ycombinator.com/item?id=13924546)

Barnes and Noble looks to be a safer option - and you can still buy directly from No Starch Press of course.

Further update: Inc.com "Amazon's Tepid Response to Counterfeiters Frustrates Sellers"


askcolor

18 Jan, 2017

Isai writes:

I am having trouble with this code in page 176:

from tkinter import * colorchooser.askcolor()

When I load it into IDLE, I get a blank canvas, and I can't close it, I have to restart the shell.

I have installed the proper ActiveTcl version (8.5), and no longer get the message giving me errors on startup.

When I run the previous code I was playing with (page 174), the canvas pops up and it all works again. Weirdly enough, the color picker pops up unprompted! I noticed that it does not bring up any buttons that appear in your book: [OK] [Cancel].

That's a bit of a gap in the book, because it doesn't make it clear that you need to create an instance of the top-level Tk widget first, before running that particular example (using tk = Tk()). So the first time you run this function: colorchooser.askcolor(), it's hanging, waiting for something that isn't there yet. Then you run the code on the previous page (which does create the Tk object), and that's when you suddenly get a popup dialog with the colorchooser in it.

So the code should really look like this:

from tkinter import *
from tkinter import colorchooser
tk = Tk()
tk.update()
colorchooser.askcolor()

When you run that, you should then get the colorchooser dialog immediately.

Update #1: One step I missed, is a call to tk.update(), which forces tk to update the screen. Once that's executed, the chooser will appear. The example is updated above.

Update #2: On Windows you need to explicitly import colorchooser for the code to work properly (example updated again).


Pro Alternatives

31 Dec, 2016

After something like 10 or more years completely ensconced in the Apple ecosystem, and now finding the price tag on the new MacBook Pros hard to justify, I'm looking around at alternatives. Before Apple, there was 7 - 8 (only occasionally fustrating) years of Linux in various flavours, so it makes sense to investigate linux-on-a-laptop options again. Looking at the Dell offerings though, it's clear they could learn from Apple's example -- at least in terms of pricing and consistency.

To start with, a higher spec'd MacBook Pro, from the US website:

Apple US (small image)

So that's £2,267 (at time of writing) for a 15" screen, i7 processor, 16GB of RAM and a 512GB solid state disk.

And for comparison, here's the same thing from the Apple UK and Apple NZ stores:

Apple UK (small image) Apple NZ (small image)

The NZ price is roughly £2,637. Apart from the fact that the US price is a few hundred pounds cheaper, they're roughly consistent (in both price, and what you get for your money). VAT (in the UK) and GST (in NZ) probably account for, at least part of, the price variation.

However, compare this with Dell's Precision series laptops. The Precision 15 5000 series (again with 15" screen, i7 processor and 512GB SSD) installed with Ubuntu Linux, comes in at a much more reasonable £1,483:

Dell US (small image)

The advantage of the Dell is that you can get a second 1TB HDD installed and the price is still less than the MacBook Pro (£1,558).

However, on the UK website, you can't order the additional hard drive, but the price is, at least, consistent (even if their website doesn't make it immediately obvious that you can order an i7 processor):

Dell - no HDD

Dell UK (small image)

However, compare with Dell NZ:

Dell NZ (small image)

That's £4,095, give or take a few pence. A price variation I can only see justified, if Dell haven't figured out international shipping, and are flying the laptop into the country in a business class seat. In addition, not only do the websites vary slightly in each country, but the configuration options vary as well. In the US you can get the additional HDD, in the UK and NZ you cannot (perhaps some different regulations applying to the ex-US models, and the additional HDD doesn't fit?). In the UK, you can get a single 1x16GB memory unit installed, in the US and NZ stores you cannot.

Conclusions? Apple: too expensive for a higher spec. Dell: either obscenely expensive, or inconsistent specifications, depending on which country I happen to be in (not to forget that if I want a bit of future proofing, it's difficult to be confident in the options). Other alternatives? A System76 Oryx Pro perhaps?

Update: Dell really is a bit of a mess. The NZ price for the XPS 15 (with ultra high def display) is only about £200 more than the UK price, but once again the configuration options look to be different between countries. Also with the XPS series, you don't have any option but to pay the Windows tax.


Python 3 on Ubuntu 16

10 Dec, 2016

Roxana T writes (excerpted):

I did look at the installation instructions in ch1 but still didn't work. I'm using Ubuntu and the built-in (is this the right word?) Python Version. It is I guess 2.7. I have the 3 version too, but I have to set it as default probably because when I launch Idle I always get Python 2.7.

Since I wrote Python for Kids, Ubuntu has changed their software installer and, at least in Ubuntu 16.04 when I try, I don't see a package installer for Idle (even though there used to be one available). So the best thing to do is to install it from the command line, by opening the Terminal and running:

sudo apt-get install idle3

(You'll need to enter the administrator password). You should see something similar to the following:

Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
  fonts-opensymbol fonts-stix libboost-date-time1.58.0
  libboost-iostreams1.58.0 libclucene-contribs1v5 libclucene-core1v5
  libcmis-0.5-5v5 libcolamd2.9.1 libeot0 libetonyek-0.1-1 libexttextcat-2.0-0
  libexttextcat-data liblangtag-common liblangtag1 libmhash2 libmwaw-0.3-3
  libmythes-1.2-0 libneon27-gnutls libodfgen-0.1-1 liborcus-0.10-0v5
  libraptor2-0 librasqal3 librdf0 librevenge-0.0-0 libsuitesparseconfig4.4.6
  libwps-0.4-4 libyajl2 lp-solve uno-libs3 ure
Use 'apt autoremove' to remove them.
The following additional packages will be installed:
  blt idle-python3.5 python3-tk tk8.6-blt2.5
Suggested packages:
  blt-demo tix python3-tk-dbg
The following NEW packages will be installed
  blt idle-python3.5 idle3 python3-tk tk8.6-blt2.5
0 to upgrade, 5 to newly install, 0 to remove and 1 not to upgrade.
Need to get 647 kB of archives.
After this operation, 2,345 kB of additional disk space will be used.
Do you want to continue? [Y/n]

Hit Y to continue, and after installation, you should be able to run idle3 from the Terminal; and then, you won't get the funny compatibility errors you're been hitting with Python2. I also see Idle for Python 3.5 available from the launcher after installation, so you don't necessarily need to use the Terminal after that, if you don't want to.

idle in the launcher


Text position in tkinter

08 Dec, 2016

Drew M writes:

I have a question I am sure I don't know :) In tkinter I am creating a game and can't figure out how to set dimensions for text. I need it on the middle. My canvas is 1000 by 1000 so I divided in half. Which is of course 500. Now again, my question is how to put it there.

Adding text to a canvas is straightforward (similar to adding any other item, such as a line, or a rectangle). You say "middle" and not "center", so I assume you don't want the text directly in the center of the canvas? I've defined a smaller canvas here, but the principle is the same:

from tkinter import *
tk = Tk()
canvas = Canvas(tk, width=100, height=100, bd=0, highlightthickness=0)
canvas.create_text(50, 50, text='text')
canvas.pack()
tk.update()

text position center

So if you don't want the center, I'm guessing your problem is that this code...

from tkinter import *
tk = Tk()
canvas = Canvas(tk, width=100, height=100, bd=0, highlightthickness=0)
canvas.create_text(50, 0, text='text')
canvas.pack()
tk.update()

...(with coordinates of 50, 0) results in partially obscured text:

text position middle

The answer, is to use the named parameter anchor in the create_text function:

canvas.create_text(50, 0, text='text', anchor=N)

The anchor parameter controls the positioning of an item in terms of its coordinates. The default value is CENTER (so using this puts the center of the text at the coordinates (50, 0) in the earlier example), but you can also use NW, N, NE (effectively top-left, top-middle, top-right), W, E (left and right), and SW, S, SE (bottom-left, bottom-middle, bottom-right). So N puts the top and middle point of the text at the coordinates (50, 0), like so:

text position N

I hope that helps.