"But it doesn't mean anything"

08 Feb, 2014

Jeremy Paxman talking with a conservative activist on the "Year of Code" (at about 9 minutes in) announces: "But it doesn't mean anything".

By the same token you could quite comfortably argue that Hanzi, or Kanji, (or Arabic, Thai, Hindi or any of the other non-Latin derived scripts) don't mean anything. But a good percentage of the world's population seem to get by quite well using them...

(Oh yeah... and the artistic looking garbage on your big screen really doesn't mean anything ツ)


Tcl/Tk warning message when starting IDLE

31 Dec, 2013

Stan W writes (NB. edited for brevity):

Over the last couple of days I have started using your great book with my two sons (13 and 15 years old). I'm reaching out to you with the following question because I have noticed other people asking about the same issue online, with at least one mentioning your book, so I think you posting the question and answer to your blog might help other people in addition to me and my sons.

We are using Mac OSX and have installed Python 3.3.3 from python.org, and are getting this message when opening IDLE:

"WARNING: The version of Tcl/Tk (8.5.9) in use may be unstable. Visit http://www.python.org/download/mac/tcltk/ for current information."

I have installed "Mac OS X 64-bit/32-bit Installer (3.3.3) for Mac OS X 10.6 and later" (file: python-3.3.3-macosx10.6.dmg) and installed the "ActiveTcl 8.6.1 for Mac OS X (10.5+, x86_64/x86)" (file: ActiveTcl8.6.1.1.297588-macosx10.5-i386-x86_64-threaded), but IDLE keeps showing the same error message.

Thank you very much for any help you can provide!

I'm not convinced ActiveTcl 8.6.1 is the right version to install - I suspect rather than installing the latest and greatest, you should be using version 8.5.15.0. Python (and thus IDLE) will probably be using the latest 8.5 version of Tcl/Tk (i.e. 8.5.x) — you're installing a completely different version (8.6), which it's not looking for at all. Hence even though you think you've re-installed, you'll still be getting the same error message.

Hope that helps.


Left and right, or top and bottom

14 Dec, 2013

Matthias writes:

My name is Matthias and I am 7 years old and I like Python. I knew a little about Python before I read your book, but I am learning more by reading your book. I like your book.

I think on page 202 is a little mistake. You wrote:

"We'll use this new object variable in the draw function to see if the ball has hit the top or bottom of the canvas:"

Shouldn't it be "left or right sides of the canvas" instead?

Hi Matthias. You're doing well to have gotten as far as you have, at 7 years of age. Well done!

You're absolutely right about the mistake, and I've updated the errata accordingly. Thanks very much for the "bug report". ツ


Problem with the turtle module

30 Oct, 2013

Mark F writes:

I think that it's a great book but I am running into one issue. If you're not too busy, I'm hoping you could answer it for me. In Chapter 8, Classes and Objects, you reintroduce the turtle module. You say that we can create 'an object of the pen class,' which makes sense.

import turtle
avery = turtle.pen()
kate = turtle.pen()

However, when I attempt to move the turtle using either one of those objects, I get this error:

avery.forward(50)
Traceback (most recent call last):
   File "\<pyshell#3>", line 1, in
     avery.forward(50)
AttributeError: 'dict' object has no attribute 'forward'

In fact, the only time I can get the turtle to move is if i simply type in turtle.forward(). I am using version 3.3 but have tried with 3.2 and encounter the same error. Please let me know why I keep getting this error so that I can keep moving forward.

If you compare your code snippet above, with the example in the book, there's one fairly obvious difference: lowercase "p" versus uppercase "P". The question is, why is it such a problem? In the turtle module, Pen and pen are two distinct things. We can see the difference if we run the Python console (or Shell), and try out the following code:

>>> import turtle
>>> turtle.pen
<function pen at 0x10117fe60>
>>> turtle.Pen
<class turtle.Turtle>

Without the brackets (i.e. without entering pen() or Pen()), Python just prints out a simple description, so we can see that pen is a function, and Pen is a class (good rule of thumb: names which start with an uppercase letter are generally classes, names with a lowercase letter are functions, variables, and so on). For the example code, we want to create a Pen object (we don't want to call the pen function) - so if you change your code to...

import turtle
avery = turtle.Pen()
kate = turtle.Pen()

...you should have a bit more success.


Loop confusion

26 Sep, 2013

Justin B writes:

I recently started the section on "For Loops" and am somewhat confused about something. The section (page 55) runs a loop for "HugeHairyPants." I setup the loop as you indicated and actually understood the result just fine.

However, I decided to add a variable in the mix and went one step further. Here is my script:

hugehairypants = ['huge', 'hairy', 'pants'] for i in hugehairypants:     print(i)     for j in hugehairypants:         print(j)         for k in hugehairypants:             print(k)

This loop doesn't seem to follow the same progression of the other loop or maybe I just don't understand it correctly. I figured it would print a variable from i and then j and then print the full loop of items in k, but it doesn't seem to do that. If you have a moment, could explain how this loop would work?

If we look at your code and mark each loop, then mark the output as well, and indent each line in terms of the loop it matches, hopefully it might help you see what's happening:

hugehairypants = ['huge', 'hairy', 'pants']
for i in hugehairypants:      # LOOP 1
    print(i)
    for j in hugehairypants:    # LOOP 2
        print(j)
        for k in hugehairypants:    # LOOP 3
            print(k)

And the output:

huge   (LOOP 1, first time)
    huge   (LOOP 2, first time)
        huge   (LOOP 3, first time)
        hairy  (LOOP 3)
        pants  (LOOP 3)
    hairy  (LOOP 2, first time)
        huge   (LOOP 3, second time)
        hairy  (LOOP 3)
        pants  (LOOP 3)
    pants  (LOOP 2, first time)
        huge   (LOOP 3, third time)
        hairy  (LOOP 3)
        pants  (LOOP 3)
hairy  (LOOP 1, first time)
    huge   (LOOP 2, second time)
        huge   (LOOP 3, fourth time)
        hairy  (LOOP 3)
        pants  (LOOP 3)
    hairy  (LOOP 2, second time)
        huge   (LOOP 3, fifth time)
        hairy  (LOOP 3)
        pants  (LOOP 3)
    pants  (LOOP 2, second time)
        huge   (LOOP 3, sixth time)
        hairy  (LOOP 3)
        pants  (LOOP 3)
pants  (LOOP 1, first time)
    huge  (LOOP 2, third time)
        huge   (LOOP 3, seventh time)
        hairy  (LOOP 3)
        pants  (LOOP 3)
    hairy  (LOOP 2, third time)
        huge   (LOOP 3, eighth time)
        hairy  (LOOP 3)
        pants  (LOOP 3)
    pants  (LOOP 2, third time)
        huge   (LOOP 3, ninth time)
        hairy  (LOOP 3)
        pants  (LOOP 3)

So loop 1 outputs the list once, loop 2 outputs the list three times, and loop 3 outputs the list nine times in total.

As a side note, we could have also altered the code to do the indentation for us:

hugehairypants = ['huge', 'hairy', 'pants']
for i in hugehairypants:      # LOOP 1
    print(i)
    for j in hugehairypants:    # LOOP 2
        print('    %s' % j)
        for k in hugehairypants:    # LOOP 3
            print('        %s' % k)

And, while sometimes it's a good idea to work things out by hand (as I did in the example output above), just so you can be sure you understand the process, we could even use counters to print out the number of times we've hit each loop, rather than figuring it out manually:

time_label = ['','first','second','third','fourth','fifth','sixth','seventh','eighth','ninth']
i_counter = 0
j_counter = 0
k_counter = 0
hugehairypants = ['huge', 'hairy', 'pants']
for i in hugehairypants:      # LOOP 1
    if i == 'huge':
        i_counter += 1
    print('%s (LOOP 1, %s time)' % (i, time_label[i_counter]))
    for j in hugehairypants:    # LOOP 2
        if j == 'huge':
            j_counter += 1
        print('    %s (LOOP 2, %s time)' % (j, time_label[j_counter]))
        for k in hugehairypants:    # LOOP 3
            if k == 'huge':
                k_counter += 1
            print('        %s (LOOP 3, %s time)' % (k, time_label[k_counter]))