Python for Kids: Python 3 – Project 3

Some people want to use my book Python for Kids for Dummies to learn Python 3. I am working through the code in the existing book, highlighting changes from Python 2 to Python 3 and providing code that will work in Python 3.

If you are using Python 2.7 you can ignore this post. This post is only for people who want to take the code in my book Python for Kids for Dummies and run it in Python 3.

Apologies also if you’re seeing

>

rather than

>

in this (or my other) posts. The way WordPress deals with the sourcecode tag is pretty much completely broken for the > character. I will do my best to fix – but WP often then breaks it after the fix.

Project 3 in the book is about getting information (input) from the user of your program. In it, the raw_input builtin from Python 2 is used. In Python 3 that builtin had its name changed to just input(). The bad news is that that means that none of the code using raw_input will work in Python 3. The good news is that you can replace raw_input by input wherever you see it and the code will work again. Alternatively, once you have completed Project 4 (it introduces the idea of putting your code in a file), you can place a single line at the start of your code that reads:

raw_input = input

Then you don’t need to change the rest of the code. This is equivalent to creating a variable called raw_input and assigning to it the built in function called input. Unfortunately, you’re still in Project 3, so that isn’t going to work. So here’s how you tackle Project 3 with Python 3.

Page 61

This code:

#Python 2.7 code:
>>> raw_input()
I am typing a response. Python won't see this until I press Enter.
"I am typing a response. Python won't see this until I press Enter."

will not work in Python 3. Watch what happens:

#Python 3 code:
>>> raw_input()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'raw_input' is not defined
>>> input()
I am typing a response. Python won't see this until I press Enter.
"I am typing a response. Python won't see this until I press Enter."
>>> 

Python 3 simply doesn’t recognise raw_input as a valid name for anything. As I mentioned above to get your Python 2.7 code working in Python 3, where you see raw_input, just write input instead:

#Python 2.7 code:
>>> raw_input("What is your guess?")
What is your guess?17
'17'

#Python 3 code:
>>> input("What is your guess?")
What is your guess?17
'17'

Page 62

All this code has problems because it uses raw_input. Replace with input instead throughout:

#Python 2.7 code:
>>> raw_input("What is your guess? ")
What is your guess? 17
'17'

>>> prompt = 'What is your guess? '
>>> raw_input(prompt)
What is your guess? 17
'17'

>>> prompt = 'What is your guess? '
>>> players_guess = raw_input(prompt)
What is your guess? 17
>>>
>>> players_guess
'17'

#Python 3 code:
>>> input("What is your guess?")
What is your guess?17
'17'

>>> input("What is your guess? ")
What is your guess? 17
'17'

>>> prompt = 'What is your guess? '
>>> input(prompt)
What is your guess? 17
'17'

>>> prompt = 'What is your guess? '
>>> players_guess = input(prompt)
What is your guess? 17
>>> players_guess
'17'

Page 63:

All code on this page is the same, and all outputs from the code is the same in Python 3 as in Python 2.7

Pages 64 and 65

With one exception, all code on these pages is the same, and all outputs from the code is the same in Python 3 as in Python 2.7. That exception relates to how division works.
Python 2.7 tries to be helpful for you when you divide. It does this by dividing integers differently to dividing floating point numbers:

#Python 2.7 code:
>>> 3/2
1
>>> -3/2
-2

Python 3 doesn’t worry. It will do the division as a floating point division whether you’re dividing integers or not.

#Python 3 code:
>>> 3/2
1.5
>>> -3/2
-1.5

If you are really desperate and want to do division Python 2.7 style, you can still do that, using the “floor” operator: // (two slashes together). Here is an example (it gives you the same results as the Python 2.7 code):

#Python 3 code:
>>> 3//2
1
>>> -3//2
-2

Page 67

All code on the first half of this page is the same, and all outputs from the code is the same in Python 3 as in Python 2.7. Page 67 gives you tips on how to work around the way Python 2.7 does division. These tips will not cause a problem in Python 3. Things will still work as you expect them, but the additional work is superfluous.

#Python 3 code:
>>> 3/2.
1.5

#Python 3 code:
>>> a=2
>>> 3/a
1
>>> 3/float(a)
1.5
>>>

In the second half of the page replace raw_input with input:

#Python 2.7 code:
>>> prompt = 'What is your guess? '
>>> raw_input(prompt)
What is your guess? 17
'17'

#Python 3 code:
>>> prompt = 'What is your guess? '
>>> input(prompt)
What is your guess? 17
'17'

Page 68

Replace raw_input with input:

#Python 2.7
>>> players_guess = raw_input(prompt)
What is your guess? 17
>>> players_guess+1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects

>>> players_guess
'17'

#Python 3 code:
>>> players_guess = input(prompt)
What is your guess? 17
>>> players_guess+1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Can't convert 'int' object to str implicitly

>>> players_guess
'17'

Note that the text of the TypeError changes a little from Python 2.7 to Python 3. The comments about raw_input always returning a string apply to input.

Pages 69-74

All code on these pages is the same, and all outputs from the code is the same in Python 3 as in Python 2.7.

Pages 75-76

Replace raw_input with input:

#Python 2.7 code:
>>> computers_number = 17
>>> prompt = 'What is your guess? '
>>> while True:
...        players_guess = raw_input(prompt)
...        if computers_number == int(players_guess):
...             print('Correct!')
...             break
...        elif computers_number > int(players_guess):
...             print('Too low')
...        else:
...             print('Too high')
...
What is your guess? 3
Too low
What is your guess? 93
Too high
What is your guess? 50
Too high
What is your guess? 30
Too high
What is your guess? 20
Too high
What is your guess? 10
Too low
What is your guess? 19
Too high
What is your guess? 16
Too low
What is your guess? 18
Too high
What is your guess? 17
Correct!

#Python 3 code:
>>> computers_number = 17
>>> prompt = 'What is your guess? '
>>> while True:
...        players_guess = input(prompt)
...        if computers_number == int(players_guess):
...             print('Correct!')
...             break
...        elif computers_number > int(players_guess):
...             print('Too low')
...        else:
...             print('Too high')
...
What is your guess? 3
Too low
What is your guess? 93
Too high
What is your guess? 50
Too high
What is your guess? 30
Too high
What is your guess? 20
Too high
What is your guess? 10
Too low
What is your guess? 19
Too high
What is your guess? 16
Too low
What is your guess? 18
Too high
What is your guess? 17
Correct!

Page 76 (still)

The break keyword is the same for both Python versions.

Page 77-81

All code on these pages is the same, and all outputs from the code is the same in Python 3 as in Python 2.7. However, behind the scenes the code is working differently in the two Python versions because of the issue with range discussed in my previous post. In short, Python 2.7 works out the members of a list before it uses them, while Python 3 will work them out “on the fly”.

Obviously, at the bottom of page 79, the heading in the readout identifies whatever version of Python 3 you’re using (in this case Python 3.3.5):

#Python 2.7 code:
Python 2.7.3 (default, Apr 14 2012, 08:58:41) [GCC] on
            linux2
Type "help", "copyright", "credits" or "license" for more
            information.
>>> random.randint(1,100)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'random' is not defined

#Python 3 code:
Python 3.3.5 (default, Mar 27 2014, 17:16:46) [GCC] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> random.randint(1,100)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'random' is not defined

Page 82

Replace raw_input with input:

#Python 2.7 code:
>>> import random
>>>
>>> computers_number = random.randint(1,100)
>>> prompt = 'What is your guess? '
>>> while True:
...     players_guess = raw_input(prompt)
...     if computers_number == int(players_guess):
...         print('Correct!')
...         break
...     elif computers_number > int(players_guess):
...         print('Too low')
...     else:
...         print('Too high')
...
What is your guess? 24
Too low
What is your guess? 86
Too low
What is your guess? 94
Too low
What is your guess? 98
Too high
What is your guess? 96
Too high
What is your guess? 95
Correct!

#Python 3 code:
>>> import random
>>>
>>> computers_number = random.randint(1,100)
>>> prompt = 'What is your guess? '
>>> while True:
...     players_guess = input(prompt)
...     if computers_number == int(players_guess):
...         print('Correct!')
...         break
...     elif computers_number > int(players_guess):
...         print('Too low')
...     else:
...         print('Too high')
...
What is your guess? 24
Too low
What is your guess? 86
Too low
What is your guess? 94
Too low
What is your guess? 98
Too low
What is your guess? 99
Correct!

The code in the Zen of Python section works the same in Python 2.7 and Python 3.

Python for Kids: Python 3 – Project 2

Some people want to use my book Python for Kids for Dummies to learn Python 3. Choosing Python 2.7 over Python 3 was a difficult decision and I have given reasons why in the book.* Nevertheless, if I write a new edition of the book, it definitely will be in Python 3, so I plan to work through the code in the existing book, highlighting changes from Python 2 to Python 3 and providing code that will work in Python 3.

I am working from the downloadable code samples (they are cross referenced to page numbers in the book), so it might be an idea to get a copy, although working from the hard copy should also be fine. Get a copy from the link in the right hand sidebar.

For Project 2, most of the code works exactly the same in Python 2.7 and Python 3. There are some changes though later in the Project (from page 50). Those changes are set out below (page numbers from the 2015 printing).

Code on Pages 36 to Page 50

All of the code on these pages works in Python 3 and gives the same output.

Code on Page 50

#Python 2.7 code:
>>> my_message = 'Hello World!'
>>> while True:
...       print(my_message),
...

Comment

In Python 2.7 you use the comma -> , to tell print to NOT include a new line at the end of what is printed.
In Python 3 print has become a function. Functions are not discussed till Project 5! Implementing this in Python 3 needs a lot of extra concepts, that I’m not going to explain here. Instead, I’m just going to give you working code. You will need to come back to this after you’ve done Project 5. Hopefully then it will make more sense.

#Python 3
>>> while True:
...       print(my_message, end=&amp;quot; &amp;quot;)
...

Code on Page 51

#Python 2.7 code:
>>> range(3)
[0, 1, 2]

Comment

In Python 2.7 range() creates a list. In Python 3 it makes something like a generator** – and generators are not even covered in the book!😦 The main difference is that, with a list, all the items that you need are created ahead of time. However, with a generator, you only create the next item when you need it. Practically, the code will work in the same manner and you won’t be able to notice any difference (see the examples on the next page). For example, the numbers produced by range in Python 3 will start at 0 and run up to the number one less than the number you give to range. The good news though is that you can ignore my warning (on page 52) about using range() if you’re running Python 3. In Python 3 range doesn’t blow out your memory, so feel free to use it for numbers as big as you like.

#Python 3 code:
>>> range(3)
range(0, 3)

Code on Page 52

#Python 2.7 code:
>>> range(3,10)
[3, 4, 5, 6, 7, 8, 9]

>>> range(3,10,2)
[3, 5, 7, 9]

Comment

See comments on generators above. You won’t be able to see the practical difference until you cover for loops (see below).

#Python 3 code:
>>> range(3,10)
range(3, 10)

>>> range(3,10,2)
range(3, 10, 2)

Code on Page 53

#Python 2.7 code:
>>> range(13,10,-1)
[13, 12, 11]

Comment

Same comments on generators. See below.

#Python 3 code:
>>> range(13,10,-1)
range(13, 10, -1)

#Python 2.7 code:
>>> for i in range(3):
...        print(i)
...
0
1
2

#Python 3 code:
>>> for i in range(3):
...        print(i)
...
0
1
2

Comment

In this example both the code and the output from the Python 2.7 and Python 3 code was the same. However, the code created the output in different ways (the Python 2.7 code created a list, while the Python 3 code created a generator). Anywhere you use range in the book, you can use it when using Python 3.

Also, using this for loop structure you can test to see whether the earlier ranges are practically the same in Python 2.7 and Python 3.
For example (from page 52):

#Python 2.7 code:
>>> range(3,10)
[3, 4, 5, 6, 7, 8, 9]

>>> range(3,10,2)
[3, 5, 7, 9]

#Python 3 code:
>>> for i in range(3,10):
...        print(i)
...
3
4
5
6
7
8
9

# note same numbers as in [3, 4, 5, 6, 7, 8, 9]

>>> for i in range(3,10,2):
...        print(i)
...
3
5
7
9

# note: odd numbers from 3 to 10

Code on Page 54

#Python 2.7 code:
>>> my_message = &amp;quot;Hello World!&amp;quot;
>>> for i in range(300):
...          print(my_message),
...

Comment

See comments on print above.

#Python 3 code:

>>> my_message = &amp;quot;Hello World!&amp;quot;
>>> for i in range(300):
...          print(my_message, end=&amp;quot; &amp;quot;)
...

Note that, in Python 2.7 when the print run had finished the >>> prompt started on a new line. However, in Python 3 the prompt >>> starts immediately after the last Hello World! on the same line.

Note:
* I had dreams of extending the book for parents to include, for example, loading applications to the cloud. Right now (March 2016, a year after I finished writing the book) Google App Engine, perhaps the easiest way to get an app live on the internet, still does not support Python 3 (although it is available through a separate service – GAE Managed VM hosting).

** It creates an “immutable sequence type” according to the docs. See Terry’s comment.

Reviewers wanted

If you’ve got a relevant blog and are interested in reviewing my book Python for Kids for Dummies, the publishers have some review copies that can be sent out. Please use the contact form on the About page to drop me a line and say you’re interested in reviewing the book. I’ll get your details and have a copy sent out.

Python for Kids Book: Project 10

In these posts I outline the contents of each project in my book Python For Kids For Dummies.  If you have questions or comments about the project listed in the title post them here. Any improvements will also be listed here.

What’s in Project 10 (Math Trainer)

Project 10 is the last of the projects in the book. Project 10 is a math trainer – it tests you on your times tables and prints them out to allow you to revise.  This project is largely an application of some of the earlier work in the book but involves a little added complexity and some thought in solving some user interface issues.  For example, I use a formatting template to present the times tables. It’s easy to print out a long list of the times tables, but not very readable, so I show you how to use a nested loop to present 5 tables at a time across the screen. This uses the slice operator [:] as well as string’s join method

In order to ask random questions I introduce random.choice.  The trainer allows you to compete against yourself on score and on time. In order to time each training session I introduce the time method from the time module – time.time().

There are three additional projects that, as at 8 September 2015, I have completed and am now waiting to be loaded online.

Improvements:

@306: The time module gives you the number of seconds since the Epoch. The Epoch started on 1 January 1970 (for Unix operating systems). Why is it 1 January 1970? No reason. It’s just one of those historical accidents that infest everything to do with time calculations.

Python for Kids Book: Project 9

In these posts I outline the contents of each project in my book Python For Kids For Dummies.  If you have questions or comments about the project listed in the title post them here. Any improvements will also be listed here.

What’s in Project 9 (Address Book)

While Project 6 introduced the concept of objects and showed how even a lowly string is actually an object, Project 9 is about how you can make your own objects using the class keyword.  Project 9 uses classes to implement a simple address book application.  I discuss the difference between a class and an instance of the class and the importance of having a reference variable (self) so that an instance can refer to itself. You learn about constructor functions and how to override a method (__repr__) to make print statements work properly on your custom method.

Since having an address book is not much use if you can’t save and update it, I also introduce the pickle module. It is used to store general Python objects (if they’re hashable!).  The address book is given save and load functions as well as a rudimentary user interface.

Improvements (1st printing):

On page 278 in the add_entry method, the second through fourth occurrences of the code

if first_name == "q":

Should be


if family_name == "q":

if email_address == "q":

and

if date_of_birth == "q":

respectively. This should be corrected in the second printing. The code samples have the correct code.

Python for Kids Book: Project 8

In these posts I outline the contents of each project in my book Python For Kids For Dummies.  If you have questions or comments about the project listed in the title post them here. Any improvements will also be listed here.

What’s in Project 8 (Silly Sentences)

Project 8 is a short project which teaches you about (old style) formatting strings. Formatting strings allow you to create a sentence template into which you can substitute words.  Four words are chosen from four lists (at random) and substituted into a sentence. The random matchings make nonsense sentences. The substitutions can be streamlined by using a data type called the tuple, so that data type is introduced and discussed. You learn how to unpack tuples and how to use a tuple to receive multiple values from a function.  The project also relies on the random.choice method.

Python for Kids Book: Project 7

In these posts I outline the contents of each project in my book Python For Kids For Dummies.  If you have questions or comments about the project listed in the title post them here. Any improvements will also be listed here.

What’s in Project 7

Project 7 (Cryptopy) introduces dictionaries as a means of encoding text using a Caesar cipher. Along the way, you are introduced to the string module and the characters in string.printable. There is some discussion about escape sequences and examples of \n and \t are given. Since you don’t want to encrypt escape sequences the slicing operator is introduced in order to take string.printable and slice off the control characters. This becomes the character set that will be encoded.

An encryption dictionary is created and each of the characters in a test message are encrypted then joined using the join method of the empty string.  I explain why this is better than adding one character after another to an existing string.  I create a matching decryption function and decryption dictionary and test the round trip (plaintext-> ciphertext -> plaintext).

The project introduces file operations by reading a message from a file then writing the encrypted (or decrypted) message to another file.  This is first done with the base file operations open and close, then the with keyword is introduced to make the housekeeping a little easier.

I demonstrate how to use your newly written encryption functions from the command line by importing the code from your own file – your own third party module!  In order for this to work seamlessly you are introduced to the __name__ attribute and the if __name__ == “__main__”: construction.

Improvements:

On page 203, the first line of code:

>>> file_object.close()

is not necessary  (because you already closed the file in the code on the previous page. It shouldn’t give you an error message though).  Ignore  it.

On page 209, there is a reference to code being in C:\Python27. This reference is only relevant if you are using Windows. On Linux and Mac things are more complicated – if the file is in the same directory that the shell is running from then you should be ok.