100% found this document useful (1 vote)
12 views

Advanced Guide to Python 3 Programming, 2nd John Hunt download

The document is an overview of the second edition of 'Advanced Guide to Python 3 Programming' by John Hunt, which has been significantly expanded and updated from the first edition. It includes new sections and chapters on advanced language features, Reactive Programming, Tkinter, performance monitoring, and package management with pip and conda. The book is designed for undergraduate students and provides numerous examples and exercises, with all code available on a GitHub repository.

Uploaded by

danickwiddy
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
12 views

Advanced Guide to Python 3 Programming, 2nd John Hunt download

The document is an overview of the second edition of 'Advanced Guide to Python 3 Programming' by John Hunt, which has been significantly expanded and updated from the first edition. It includes new sections and chapters on advanced language features, Reactive Programming, Tkinter, performance monitoring, and package management with pip and conda. The book is designed for undergraduate students and provides numerous examples and exercises, with all code available on a GitHub repository.

Uploaded by

danickwiddy
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 74

Advanced Guide to Python 3 Programming, 2nd John

Hunt install download

https://ebookmeta.com/product/advanced-guide-to-
python-3-programming-2nd-john-hunt/

Download more ebook from https://ebookmeta.com


Undergraduate Topics in Computer Science

John Hunt

Advanced Guide
to Python 3
Programming
Second Edition
Undergraduate Topics in Computer Science

Series Editor
Ian Mackie, University of Sussex, Brighton, UK

Advisory Editors
Samson Abramsky , Department of Computer Science, University of Oxford,
Oxford, UK
Chris Hankin , Department of Computing, Imperial College London, London,
UK
Mike Hinchey , Lero – The Irish Software Research Centre, University of
Limerick, Limerick, Ireland
Dexter C. Kozen, Department of Computer Science, Cornell University, Ithaca,
NY, USA
Andrew Pitts , Department of Computer Science and Technology, University of
Cambridge, Cambridge, UK
Hanne Riis Nielson , Department of Applied Mathematics and Computer
Science, Technical University of Denmark, Kongens Lyngby, Denmark
Steven S. Skiena, Department of Computer Science, Stony Brook University,
Stony Brook, NY, USA
Iain Stewart , Department of Computer Science, Durham University, Durham,
UK
Joseph Migga Kizza, College of Engineering and Computer Science, The
University of Tennessee-Chattanooga, Chattanooga, TN, USA
‘Undergraduate Topics in Computer Science’ (UTiCS) delivers high-quality instruc-
tional content for undergraduates studying in all areas of computing and information
science. From core foundational and theoretical material to final-year topics and
applications, UTiCS books take a fresh, concise, and modern approach and are ideal
for self-study or for a one- or two-semester course. The texts are all authored by
established experts in their fields, reviewed by an international advisory board, and
contain numerous examples and problems, many of which include fully worked
solutions.
The UTiCS concept relies on high-quality, concise books in softback format, and
generally a maximum of 275–300 pages. For undergraduate textbooks that are likely
to be longer, more expository, Springer continues to offer the highly regarded Texts
in Computer Science series, to which we refer potential authors.
John Hunt

Advanced Guide to Python 3


Programming
Second Edition
John Hunt
Midmarsh Technology Ltd.
Chippenham, Wiltshire, UK

ISSN 1863-7310 ISSN 2197-1781 (electronic)


Undergraduate Topics in Computer Science
ISBN 978-3-031-40335-4 ISBN 978-3-031-40336-1 (eBook)
https://doi.org/10.1007/978-3-031-40336-1

© Springer Nature Switzerland AG 2019, 2023

This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part of
the material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation,
broadcasting, reproduction on microfilms or in any other physical way, and transmission or information
storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology
now known or hereafter developed.
The use of general descriptive names, registered names, trademarks, service marks, etc. in this publication
does not imply, even in the absence of a specific statement, that such names are exempt from the relevant
protective laws and regulations and therefore free for general use.
The publisher, the authors, and the editors are safe to assume that the advice and information in this book
are believed to be true and accurate at the date of publication. Neither the publisher nor the authors or
the editors give a warranty, expressed or implied, with respect to the material contained herein or for any
errors or omissions that may have been made. The publisher remains neutral with regard to jurisdictional
claims in published maps and institutional affiliations.

This Springer imprint is published by the registered company Springer Nature Switzerland AG
The registered company address is: Gewerbestrasse 11, 6330 Cham, Switzerland
For Denise, my wife, my soulmate, my best
friend.
Preface to the Second Edition

This second edition represents a significant expansion of the material in the first
edition, as well as an update of that book from Python 3.7 to 3.12.
This book includes whole new sections on advanced language features, Reactive
Programming in Python and data analysts. New chapters on working with Tkinter,
on event handling with Tkinter and a simple drawing application using Tkinter have
been added. A new chapter on performance monitoring and profiling has also been
added. A chapter on pip and conda is included at the end of the book.
In all there are 18 completely new chapters that take you far further on your Python
journey. Enjoy the book and I hope you find it useful.

Chippenham, UK John Hunt

vii
Preface to the First Edition

Some of the key aspects of this book are


1. It assumes knowledge of Python 3 and of concepts such as functions, classes,
protocols, abstract base classes, decorators, iterables and collection types (such
as list and tuple).
2. However, the book assumes very little knowledge or experience of the topics
presented.
3. The book is divided into eleven topic areas: advanced language features,
Computer Graphics, games, testing, file input/output, database access, logging,
concurrency and parallelism, Reactive Programming, network programming and
data analytics.
4. Each topic in the book has an introductory chapter followed by chapters that
delve into that topic.
5. The book includes exercises at the end of most chapters.
6. All code examples (and exercise solutions) are provided on line in a GitHub
repository.

What You Need

You can of course just read this book; however following the examples in this book
will ensure that you get as much as possible out of the content. For this you will need
a computer.
Python is a cross-platform programming language, and as such you can use Python
on a Windows PC, a Linux box, an Apple Mac, etc. So you are not tied to a particular
type of operating system; you can use whatever you have available.
However you will need to install some software on that computer. At a minimum
you will need Python. The focus of this book is Python 3 so that is the version that
is assumed for all examples and exercises. As Python is available for a wide range

ix
x Preface to the First Edition

of platforms from Windows, to Mac OS and Linux, you will need to ensure that you
download the version for your operating system.
Python can be downloaded from the main Python website which can be found at
http://www.python.org/.

You will also need some form of editor to write your programs. There are numerous
generic programming editors available for different operating systems with VIM on
Linux, Notepad++ on Windows and Sublime Text on windows and Macs being
popular choices.
However, using an Integrated Development Environment (IDE) editor such as
PyCharm, Visual Studio Code or Spyder can make writing and running your programs
much easier.
However, this book does not assume any particular editor, IDE or environment
(other than Python 3 itself).

Conventions

Throughout this book you will find a number of conventions used for text styles.
These text styles distinguish between different kinds of information. Code words,
variable and Python values, used within the main body of the text, are shown using
a Courier font. A block of Python code is set out as shown here:
Preface to the First Edition xi

def draw_koch(size, depth):


if depth > 0:
for angle in ANGLES:
draw_koch(size / 3, depth - 1)
turtle.left(angle)
else:
turtle.forward(size)
# Draw three sides of snowflake
for_in range(3):
draw_koch(SIZE_OF_SNOWFLAKE, depth)
turtle.right(120)

Note that keywords and points of interest are shown in bold font.
Any command line or user input is shown in standard font as shown below, for
example:
Hello, world
Enter your name: John
Hello John

Example Code and Sample Solutions

The examples used in this book (along with sample solutions for the exercises at the
end of most chapters) are available in a GitHub repository. GitHub provides a web
interface to Git, as well as a server environment hosting Git.
Git is a version control system typically used to manage source code files (such
as those used to create systems in programming languages such as Python but also
Java, C#, C++ and Scala). Systems such as Git are very useful for collaborative
development as they allow multiple people to work on an implementation and to
merge their work together. They also provide a useful historical view of the code
(which also allows developers to roll back changes if modifications prove to be
unsuitable).
The GitHub repository for this book can be found at:
• https://github.com/johnehunt/advancedpython3_2nd
If you already have Git installed on your computer, then you can clone (obtain a
copy of) the repository locally using:
git clone https://github.com/johnehunt/advancedpyth
on3_2nd.git
If you do not have Git, then you can obtain a zip file of the examples using
https://github.com/johnehunt/advancedpython3_2nd/arc
hive/refs/heads/main.zip
xii Preface to the First Edition

You can of course install Git yourself if you wish. To do this, see https://git-scm.
com/downloads. Versions of the Git client for Mac OS, Windows and Linux/Unix
are available here.
However, many IDEs such as PyCharm come with Git support and so offer another
approach to obtaining a Git repository.
For more information on Git see http://git-scm.com/doc. This Git guide
provides a very good primer and is highly recommended.

Acknowledgement I would like to thank Phoebe Hunt for creating the pixel images used for the
Starship Meteors game in Chap. 22.
Contents

1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Useful Python Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

Part I Advanced Language Features


2 Python Type Hints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2 Pythons Type System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.3 The Challenge for Python Developers . . . . . . . . . . . . . . . . . . . . . . 8
2.4 Static Typing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.5 Python Type Hints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.6 Type Hint Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.7 Type Hints for Multiple Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.8 The Self Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.9 The Benefits of Type Hints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.10 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.11 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3 Class Slots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.2 The Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.3 Slots to the Rescue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.4 Performance Benefits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.5 Why Not Use Slots? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.6 Online Resource . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
4 Weak References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.2 How Garbage Collection Works: Reference Counting . . . . . . . . 23
4.3 Weak References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4.4 When to Use Weak References . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

xiii
xiv Contents

4.5 The Weakref Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26


4.6 Creating Weak References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
4.7 Retrieving Objects from Weak References . . . . . . . . . . . . . . . . . . 28
4.8 The WeakValueDicitonary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
4.9 WeakKeyDictionary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
4.10 Proxy Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
4.11 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
5 Data Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.2 A Traditional Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.3 Defining Data Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
5.4 Defining Additional Behaviour . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
5.5 The Dataclass Decorator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
5.6 Custom Factory for Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
5.7 Immutable Dataclasses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
5.8 Data Classes and Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
5.9 Post Initialisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
5.10 Initialisation Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
5.11 Positional Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
5.12 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
6 Structural Pattern Matching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
6.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
6.2 The Match Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
6.3 Matching Classes with Positional Attributes . . . . . . . . . . . . . . . . . 50
6.4 Matching Against Standard Classes . . . . . . . . . . . . . . . . . . . . . . . . 51
6.5 Online Resource . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
7 Working with pprint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
7.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
7.2 The pprint Data Printer Module . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
7.3 Basic pprint Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
7.4 Changing the Width . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
7.5 Changing the Depth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.6 Managing the Indentation Level . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
7.7 Reducing Line Breaks Using Compact . . . . . . . . . . . . . . . . . . . . . 59
7.8 The pformat Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
7.9 The saferepr() Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
7.10 Using the PrettyPrinter Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
7.11 Online Resource . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
8 Shallow v Deep Copy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
8.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
8.2 Copying a List of Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
8.3 The Problem with Copying . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
Contents xv

8.4 The Copy Module to the Rescue . . . . . . . . . . . . . . . . . . . . . . . . . . . 68


8.5 Using the deepcopy() Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
8.6 Online Resource . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
9 The __init__ Versus __new__ and __call . . . . . . . . . . . . . . . . . . . . . . . . . 71
9.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
9.2 The __new__ and __init__ Methods . . . . . . . . . . . . . . . . . . . . . . . 71
9.3 The __new__ Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
9.4 When to Use the __new__ Method . . . . . . . . . . . . . . . . . . . . . . . . . 73
9.5 Using __new__ to Create a Singleton Object . . . . . . . . . . . . . . . . 74
9.6 The __init__ Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
9.7 Can __new__ and __init__ Be Used Together? . . . . . . . . . . . . . . 76
9.8 The __call__ Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
9.9 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
10 Python Metaclasses and Meta Programming . . . . . . . . . . . . . . . . . . . . . 79
10.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
10.2 Metaprogramming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
10.3 Decorators as a Form of Metaprogramming . . . . . . . . . . . . . . . . . 81
10.4 Metaclasses for Metaprogramming . . . . . . . . . . . . . . . . . . . . . . . . 83
10.4.1 Singleton Metaclass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
10.5 Exec and Eval for Metaprogramming . . . . . . . . . . . . . . . . . . . . . . 85
10.5.1 The exec() Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
10.5.2 The eval() Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
10.5.3 eval Versus exec() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

Part II Computer Graphics and GUIs


11 Introduction to Computer Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
11.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
11.2 Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
11.3 The Graphical Computer Era . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
11.4 Interactive and Non Interactive Graphics . . . . . . . . . . . . . . . . . . . . 93
11.5 Pixels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
11.6 Bit Map Versus Vector Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
11.7 Buffering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
11.8 Python and Computer Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
11.9 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
11.10 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
12 Python Turtle Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
12.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
12.2 The Turtle Graphics Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
12.2.1 The Turtle Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
12.2.2 Basic Turtle Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
12.2.3 Drawing Shapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
12.2.4 Filling Shapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
xvi Contents

12.3 Other Graphics Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105


12.4 3D Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
12.4.1 PyOpenGL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
12.5 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
12.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
13 Computer Generated Art . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
13.1 Creating Computer Art . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
13.2 A Computer Art Generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
13.3 Fractals in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
13.4 The Koch Snowflake . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
13.5 Mandelbrot Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
13.6 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
13.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
14 Introduction to Matplotlib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
14.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
14.2 Matplotlib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
14.3 Plot Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
14.4 Matplotlib Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
14.4.1 Backend Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
14.4.2 The Artist Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
14.4.3 The Scripting Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
14.5 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
15 Graphing with Matplotlib Pyplot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
15.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
15.2 The pyplot API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
15.3 Line Graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
15.3.1 Coded Format Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
15.4 Scatter Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
15.4.1 When to Use Scatter Graphs . . . . . . . . . . . . . . . . . . . . . 134
15.5 Pie Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
15.5.1 Expanding Segments . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
15.5.2 When to Use Pie Charts . . . . . . . . . . . . . . . . . . . . . . . . . 138
15.6 Bar Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
15.6.1 Horizontal Bar Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
15.6.2 Coloured Bars . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
15.6.3 Stacked Bar Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
15.6.4 Grouped Bar Charts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
15.7 Figures and Subplots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
15.8 3D Graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
15.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
Contents xvii

16 Graphical User Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151


16.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
16.2 GUIs and WIMPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
16.3 Windowing Frameworks for Python . . . . . . . . . . . . . . . . . . . . . . . . 153
16.3.1 Platform-Independent GUI Libraries . . . . . . . . . . . . . . 154
16.3.2 Platform-Specific GUI Libraries . . . . . . . . . . . . . . . . . . 154
16.4 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
17 Tkinter GUI Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
17.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
17.2 Tkinter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
17.3 Windows as Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
17.4 Key Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
17.4.1 The Tk Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
17.4.2 TK Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
17.4.3 The TopLevel Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
17.4.4 The Frame Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
17.4.5 Dialogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
17.4.6 The Canvas Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
17.5 The Class Inheritance Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
17.5.1 Layout Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
17.6 A Simple Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
17.7 Tkinter Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
17.7.1 Mac Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
17.7.2 Windows Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
17.8 GUI Builders for Tkinter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
17.9 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
17.10 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
18 Events in Tkinter User Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
18.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
18.2 Event Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
18.3 What is Event Handling? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
18.4 What Are Event Handlers? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
18.5 Event Binders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
18.6 Virtual Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
18.7 Event Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173
18.8 What Types of Event Are There? . . . . . . . . . . . . . . . . . . . . . . . . . . 174
18.9 Binding an Event to an Event Handler . . . . . . . . . . . . . . . . . . . . . . 175
18.10 Implementing Event Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
18.11 An Interactive GUI Application . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
18.12 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
18.13 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
xviii Contents

19 PyDraw Tkinter Example Application . . . . . . . . . . . . . . . . . . . . . . . . . . 185


19.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
19.2 The PyDraw Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
19.3 The Structure of the Application . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
19.3.1 Model, View and Controller Architecture . . . . . . . . . . 188
19.3.2 PyDraw MVC Architecture . . . . . . . . . . . . . . . . . . . . . . 189
19.3.3 Additional Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
19.3.4 Object Relationships . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
19.4 The Interactions Between Objects . . . . . . . . . . . . . . . . . . . . . . . . . 191
19.4.1 The PyDrawApp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
19.5 The PyDrawView Constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
19.5.1 Changing the Application Mode . . . . . . . . . . . . . . . . . . 193
19.5.2 Adding a Graphic Object . . . . . . . . . . . . . . . . . . . . . . . . 193
19.6 The Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
19.6.1 The PyDrawConstants Class . . . . . . . . . . . . . . . . . . . . . 194
19.6.2 The PyDrawView Class . . . . . . . . . . . . . . . . . . . . . . . . . 195
19.6.3 The PyDrawMenuBar Class . . . . . . . . . . . . . . . . . . . . . . 196
19.6.4 The PyDrawController Class . . . . . . . . . . . . . . . . . . . . . 196
19.6.5 The DrawingModel Class . . . . . . . . . . . . . . . . . . . . . . . . 197
19.6.6 The DrawingView Class . . . . . . . . . . . . . . . . . . . . . . . . . 198
19.6.7 The DrawingController Class . . . . . . . . . . . . . . . . . . . . . 198
19.6.8 The Figure Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
19.6.9 The Square Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
19.6.10 The Circle Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
19.6.11 The Line Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
19.6.12 The Text Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
19.7 Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
19.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201

Part III Computer Games


20 Introduction to Games Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
20.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
20.2 Games Frameworks and Libraries . . . . . . . . . . . . . . . . . . . . . . . . . 205
20.3 Python Games Development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
20.4 Using Pygame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
20.5 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
21 Building Games with Pygame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
21.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
21.2 The Display Surface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
21.3 Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
21.3.1 Event Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
21.3.2 Event Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212
21.3.3 The Event Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
Contents xix

21.4 A First pygame Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214


21.5 Further Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
21.6 A More Interactive pygame Application . . . . . . . . . . . . . . . . . . . . 219
21.7 Alternative Approach to Processing Input Devices . . . . . . . . . . . 221
21.8 pygame Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
21.9 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
22 StarshipMeteors Pygame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
22.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
22.2 Creating a Spaceship Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
22.3 The Main Game Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
22.4 The GameObject Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
22.5 Displaying the Starship . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229
22.6 Moving the Spaceship . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
22.7 Adding a Meteor Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233
22.8 Moving the Meteors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
22.9 Identifying a Collision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236
22.10 Identifying a Win . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
22.11 Increasing the Number of Meteors . . . . . . . . . . . . . . . . . . . . . . . . . 238
22.12 Pausing the Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
22.13 Displaying the Game Over Message . . . . . . . . . . . . . . . . . . . . . . . 239
22.14 The StarshipMeteors Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
22.15 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
22.16 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244

Part IV Testing
23 Introduction to Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
23.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
23.2 Types of Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
23.3 What Should Be Tested? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
23.4 Types of Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
23.4.1 Unit Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250
23.4.2 Integration Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
23.4.3 System Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
23.4.4 Installation/Upgrade Testing . . . . . . . . . . . . . . . . . . . . . 252
23.4.5 Smoke Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
23.5 Automating Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
23.6 Test-Driven Development . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253
23.6.1 The TDD Cycle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253
23.6.2 Test Complexity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254
23.6.3 Refactoring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255
23.7 Design for Testability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255
23.7.1 Testability Rules of Thumb . . . . . . . . . . . . . . . . . . . . . . 255
23.8 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255
23.9 Book Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
xx Contents

24 PyTest Testing Framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257


24.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
24.2 What is PyTest? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
24.3 Setting up PyTest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
24.4 A Simple PyTest Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
24.5 Working with PyTest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
24.6 Parameterised Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
24.7 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
24.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
25 Mocking for Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
25.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
25.2 Why Mock? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271
25.3 What is Mocking? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
25.4 Common Mocking Framework Concepts . . . . . . . . . . . . . . . . . . . 273
25.5 Mocking Frameworks for Python . . . . . . . . . . . . . . . . . . . . . . . . . . 274
25.6 The Unittest.Mock Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274
25.6.1 Mock and Magic Mock Classes . . . . . . . . . . . . . . . . . . . 275
25.6.2 The Patchers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276
25.6.3 Mocking Returned Objects . . . . . . . . . . . . . . . . . . . . . . . 277
25.6.4 Validating Mocks Have Been Called . . . . . . . . . . . . . . . 278
25.7 Mock and MagicMock Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
25.7.1 Naming Your Mocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
25.7.2 Mock Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
25.7.3 Attributes on Mock Classes . . . . . . . . . . . . . . . . . . . . . . 279
25.7.4 Mocking Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280
25.7.5 Mocking Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280
25.7.6 Raising Exceptions with Mocks . . . . . . . . . . . . . . . . . . . 281
25.7.7 Applying Patch to Every Test Method . . . . . . . . . . . . . 281
25.7.8 Using Patch as a Context Manager . . . . . . . . . . . . . . . . 281
25.8 Mock Where You Use It . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282
25.9 Patch Order Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282
25.10 How Many Mocks? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
25.11 Mocking Considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
25.12 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284
25.13 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284

Part V File Input/Output


26 Introduction to Files, Paths and IO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289
26.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289
26.2 File Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
26.3 Paths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 293
26.4 File Input/Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
Contents xxi

26.5 Sequential Access versus Random Access . . . . . . . . . . . . . . . . . . 296


26.6 Files and I/O in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
26.7 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
27 Reading and Writing Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
27.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
27.2 Obtaining References to Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
27.3 Reading Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
27.4 File Contents Iteration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
27.5 Writing Data to Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
27.6 Using Files and with Statements . . . . . . . . . . . . . . . . . . . . . . . . . . . 303
27.7 The Fileinput Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303
27.8 Renaming Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304
27.9 Deleting Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304
27.10 Random Access Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
27.11 Directories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306
27.12 Temporary Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307
27.13 Working with Paths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309
27.14 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312
27.15 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313
28 Stream IO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315
28.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315
28.2 What is a Stream? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315
28.3 Python Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316
28.4 IOBase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317
28.5 Raw IO/UnBuffered IO Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
28.6 Binary IO/Buffered IO Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 318
28.7 Text Stream Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320
28.8 Stream Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
28.9 Closing Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322
28.10 Returning to the Open() Function . . . . . . . . . . . . . . . . . . . . . . . . . . 322
28.11 Online Resource . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
28.12 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
29 Working with CSV Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
29.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
29.2 CSV Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
29.2.1 The CSV Writer Class . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
29.2.2 The CSV Reader Class . . . . . . . . . . . . . . . . . . . . . . . . . . 327
29.2.3 The CSV DictWriter Class . . . . . . . . . . . . . . . . . . . . . . . 328
29.2.4 The CSV DictReader Class . . . . . . . . . . . . . . . . . . . . . . 329
29.3 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
29.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
xxii Contents

30 Working with Excel Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333


30.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333
30.2 Excel Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333
30.3 The Openpyxl. Workbook Class . . . . . . . . . . . . . . . . . . . . . . . . . . . 334
30.4 The Openpyxl. WorkSheet Objects . . . . . . . . . . . . . . . . . . . . . . . . . 334
30.5 Working with Cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334
30.6 Sample Excel File Creation Application . . . . . . . . . . . . . . . . . . . . 335
30.7 Loading a Workbook from an Excel File . . . . . . . . . . . . . . . . . . . . 336
30.8 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338
30.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338
31 Regular Expressions in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
31.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
31.2 What Are Regular Expressions? . . . . . . . . . . . . . . . . . . . . . . . . . . . 341
31.3 Regular Expression Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342
31.3.1 Pattern Metacharacters . . . . . . . . . . . . . . . . . . . . . . . . . . 342
31.3.2 Special Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
31.3.3 Sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344
31.4 The Python re Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
31.5 Working with Python Regular Expressions . . . . . . . . . . . . . . . . . . 345
31.5.1 Using Raw Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
31.5.2 Simple Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346
31.5.3 The Match Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346
31.5.4 The search() Function . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
31.5.5 The match() Function . . . . . . . . . . . . . . . . . . . . . . . . . . . 348
31.5.6 The Difference Between Matching
and Searching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
31.5.7 The finadall() Function . . . . . . . . . . . . . . . . . . . . . . . . . . 349
31.5.8 The finditer() Function . . . . . . . . . . . . . . . . . . . . . . . . . . 349
31.5.9 The split() Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
31.5.10 The sub() Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
31.5.11 The compile() Function . . . . . . . . . . . . . . . . . . . . . . . . . . 351
31.6 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
31.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354

Part VI Database Access


32 Introduction to Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
32.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
32.2 What Is a Database? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
32.2.1 Data Relationships . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
32.2.2 The Database Schema . . . . . . . . . . . . . . . . . . . . . . . . . . . 361
32.3 SQL and Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363
32.4 Data Manipulation Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
32.5 Transactions in Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365
32.6 Further Reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366
Contents xxiii

33 Python DB-API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369


33.1 Accessing a Database from Python . . . . . . . . . . . . . . . . . . . . . . . . 369
33.2 The DB-API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369
33.2.1 The Connect Function . . . . . . . . . . . . . . . . . . . . . . . . . . . 370
33.2.2 The Connection Object . . . . . . . . . . . . . . . . . . . . . . . . . . 370
33.2.3 The Cursor Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371
33.2.4 Mappings from Database Types to Python Types . . . . 372
33.2.5 Generating Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
33.2.6 Row Descriptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373
33.3 Transactions in PyMySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374
33.4 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375
34 PyMySQL Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
34.1 The PyMySQL Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
34.2 Working with the PyMySQL Module . . . . . . . . . . . . . . . . . . . . . . 377
34.2.1 Importing the Module . . . . . . . . . . . . . . . . . . . . . . . . . . . 378
34.2.2 Connect to the Database . . . . . . . . . . . . . . . . . . . . . . . . . 378
34.2.3 Obtaining the Cursor Object . . . . . . . . . . . . . . . . . . . . . . 379
34.2.4 Using the Cursor Object . . . . . . . . . . . . . . . . . . . . . . . . . 379
34.2.5 Obtaining Information About the Results . . . . . . . . . . . 380
34.2.6 Fetching Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 380
34.2.7 Close the Connection . . . . . . . . . . . . . . . . . . . . . . . . . . . 381
34.3 Complete PyMySQL Query Example . . . . . . . . . . . . . . . . . . . . . . 381
34.4 Inserting Data to the Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
34.5 Updating Data in the Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . 384
34.6 Deleting Data in the Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385
34.7 Creating Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
34.8 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
34.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387

Part VII Logging


35 Introduction to Logging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
35.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
35.2 Why Log? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
35.3 What is the Purpose of Logging? . . . . . . . . . . . . . . . . . . . . . . . . . . 392
35.4 What Should You Log? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392
35.5 What not to Log . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393
35.6 Why not Just Use Print? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
35.7 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395
36 Logging in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397
36.1 The Logging Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397
36.2 The Logger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398
36.3 Controlling the Amount of Information Logged . . . . . . . . . . . . . . 399
36.4 Logger Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401
xxiv Contents

36.5 Default Logger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402


36.6 Module Level Loggers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 403
36.7 Logger Hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
36.8 Formatters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405
36.8.1 Formatting Log Messages . . . . . . . . . . . . . . . . . . . . . . . . 406
36.8.2 Formatting Log Output . . . . . . . . . . . . . . . . . . . . . . . . . . 406
36.9 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
36.10 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
37 Advanced Logging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
37.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
37.2 Handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
37.2.1 Setting the Root Output Handler . . . . . . . . . . . . . . . . . . 411
37.2.2 Programmatically Setting the Handler . . . . . . . . . . . . . 412
37.2.3 Multiple Handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413
37.3 Filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415
37.4 Logger Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416
37.5 Performance Considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418
37.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 419

Part VIII Concurrency and Parallelism


38 Introduction to Concurrency and Parallelism . . . . . . . . . . . . . . . . . . . . 423
38.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423
38.2 Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423
38.3 Parallelism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425
38.4 Distribution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426
38.5 Grid Computing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427
38.6 Concurrency and Synchronisation . . . . . . . . . . . . . . . . . . . . . . . . . 428
38.7 Object Orientation and Concurrency . . . . . . . . . . . . . . . . . . . . . . . 428
38.8 Threads V Processes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 429
38.9 Some Terminology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
38.10 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
39 Threading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433
39.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433
39.2 Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433
39.2.1 Thread States . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433
39.2.2 Creating a Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434
39.2.3 Instantiating the Thread Class . . . . . . . . . . . . . . . . . . . . 435
39.3 The Thread Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436
39.4 The Threading Module Functions . . . . . . . . . . . . . . . . . . . . . . . . . . 438
39.5 Passing Arguments to a Thread . . . . . . . . . . . . . . . . . . . . . . . . . . . . 438
39.6 Extending the Thread Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440
39.7 Daemon Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441
Contents xxv

39.8 Naming Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 442


39.9 Thread Local Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 442
39.10 Timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444
39.11 The Global Interpreter Lock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445
39.12 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446
39.13 Exercise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446
40 MultiProcessing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
40.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
40.2 The Process Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
40.3 Working with the Process Class . . . . . . . . . . . . . . . . . . . . . . . . . . . 451
40.4 Alternative Ways to Start a Process . . . . . . . . . . . . . . . . . . . . . . . . 453
40.5 Using a Pool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454
40.6 Exchanging Data Between Processes . . . . . . . . . . . . . . . . . . . . . . . 458
40.7 Sharing State Between Processes . . . . . . . . . . . . . . . . . . . . . . . . . . 460
40.7.1 Process Shared Memory . . . . . . . . . . . . . . . . . . . . . . . . . 460
40.8 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 461
40.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 462
41 Inter Thread/Process Synchronisation . . . . . . . . . . . . . . . . . . . . . . . . . . . 463
41.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 463
41.2 Using a Barrier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 463
41.3 Event Signalling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 467
41.4 Synchronising Concurrent Code . . . . . . . . . . . . . . . . . . . . . . . . . . . 469
41.5 Python Locks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 470
41.6 Python Conditions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 472
41.7 Python Semaphores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475
41.8 The Concurrent Queue Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 476
41.9 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 478
41.10 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 478
42 Futures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481
42.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481
42.2 The Need for a Future . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481
42.3 Futures in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 482
42.3.1 Future Creation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 483
42.3.2 Simple Example Future . . . . . . . . . . . . . . . . . . . . . . . . . . 483
42.4 Running Multiple Futures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 485
42.4.1 Waiting for All Futures to Complete . . . . . . . . . . . . . . . 486
42.4.2 Processing Results as Completed . . . . . . . . . . . . . . . . . 488
42.5 Processing Future Results Using a Callback . . . . . . . . . . . . . . . . . 489
42.6 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 490
42.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 490
xxvi Contents

43 Concurrency with AsyncIO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493


43.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493
43.2 Asynchronous IO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 493
43.3 Async IO Event Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494
43.4 The Async and Await Keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . 495
43.4.1 Using Async and Await . . . . . . . . . . . . . . . . . . . . . . . . . . 496
43.5 Async IO Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498
43.6 Running Multiple Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 500
43.6.1 Collating Results from Multiple Tasks . . . . . . . . . . . . . 500
43.6.2 Handling Task Results as They Are Made
Available . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 501
43.7 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502
43.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502
44 Performance Monitoring and Profiling . . . . . . . . . . . . . . . . . . . . . . . . . . 505
44.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 505
44.2 Why Monitor Performance and Memory? . . . . . . . . . . . . . . . . . . . 505
44.3 Performance Monitoring and Profiling . . . . . . . . . . . . . . . . . . . . . 506
44.4 Performance Monitoring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507
44.4.1 The Time Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 507
44.4.2 The Timeit Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508
44.4.3 The Psutil Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510
44.5 Python Profiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511
44.5.1 The cProfile Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511
44.5.2 The Line_Profiler Module . . . . . . . . . . . . . . . . . . . . . . . 511
44.5.3 The Memory_Profiler Module . . . . . . . . . . . . . . . . . . . . 512
44.5.4 Additional Third-Party Libraries . . . . . . . . . . . . . . . . . . 512
44.6 Profiling with cProfile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 512
44.7 Memory Profiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515
44.8 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517

Part IX Reactive Programming


45 Reactive Programming Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521
45.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521
45.2 What Is a Reactive Application? . . . . . . . . . . . . . . . . . . . . . . . . . . . 521
45.3 The ReactiveX Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 522
45.4 The Observer Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 522
45.5 Hot and Cold Observables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 523
45.6 Differences Between Event Driven Programming
and Reactive Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 524
45.7 Advantages of Reactive Programming . . . . . . . . . . . . . . . . . . . . . . 525
45.8 Disadvantages of Reactive Programming . . . . . . . . . . . . . . . . . . . 525
45.9 The RxPy Reactive Programming Framework . . . . . . . . . . . . . . . 526
45.10 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 526
Contents xxvii

46 RxPy Observables, Observers and Subjects . . . . . . . . . . . . . . . . . . . . . . 527


46.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 527
46.2 RxPy Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 527
46.3 Observables in RxPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 527
46.4 Observers in RxPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 528
46.5 Multiple Subscribers/Observers . . . . . . . . . . . . . . . . . . . . . . . . . . . 530
46.6 Subjects in RxPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 531
46.7 Observer Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 534
46.7.1 Available Schedulers . . . . . . . . . . . . . . . . . . . . . . . . . . . . 535
46.8 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536
46.9 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536
47 RxPy Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537
47.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537
47.2 Reactive Programming Operators . . . . . . . . . . . . . . . . . . . . . . . . . . 537
47.3 Piping Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 538
47.4 Creational Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539
47.5 Transformational Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539
47.6 Combinatorial Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 541
47.7 Filtering Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 542
47.8 Mathematical Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543
47.9 Chaining Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 544
47.10 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 546
47.11 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 546

Part X Network Programming


48 Introduction to Sockets and Web Services . . . . . . . . . . . . . . . . . . . . . . . 551
48.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 551
48.2 Sockets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 551
48.3 Web Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 552
48.4 Addressing Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 552
48.5 Localhost . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 553
48.6 Port Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 554
48.7 IPv4 Versus IPv6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 555
48.8 Sockets and Web Services in Python . . . . . . . . . . . . . . . . . . . . . . . 555
48.9 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 556
49 Sockets in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 557
49.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 557
49.2 Socket to Socket Communication . . . . . . . . . . . . . . . . . . . . . . . . . . 557
49.3 Setting up a Connection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 558
49.4 An Example Client Server Application . . . . . . . . . . . . . . . . . . . . . 558
49.4.1 The System Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . 558
49.4.2 Implementing the Server Application . . . . . . . . . . . . . . 559
xxviii Contents

49.4.3 Socket Types and Domains . . . . . . . . . . . . . . . . . . . . . . . 560


49.4.4 Implementing the Client Application . . . . . . . . . . . . . . 561
49.5 The Socketserver Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 562
49.6 Http Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 565
49.7 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 567
49.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 568
50 Web Services in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 571
50.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 571
50.2 RESTful Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 571
50.3 A RESTful API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 572
50.4 Python Web Frameworks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 573
50.5 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 574
51 Flask Web Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575
51.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575
51.2 Flask . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575
51.3 Hello World in Flask . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 576
51.3.1 Using JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 576
51.4 Implementing a Flask Web Service . . . . . . . . . . . . . . . . . . . . . . . . 577
51.4.1 A Simple Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 577
51.4.2 Providing Routing Information . . . . . . . . . . . . . . . . . . . 577
51.5 Running the Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 578
51.6 Invoking the RESTFul Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . 579
51.6.1 The Final Solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 580
51.7 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 580
52 Flask Bookshop Web Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583
52.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583
52.2 Building a Flask Bookshop Service . . . . . . . . . . . . . . . . . . . . . . . . 583
52.3 The Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 583
52.4 The Domain Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585
52.5 Encoding Books into JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 586
52.6 Setting Up the GET Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 588
52.7 Deleting a Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 589
52.8 Adding a New Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 590
52.9 Updating a Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 592
52.10 What Happens if We Get It Wrong? . . . . . . . . . . . . . . . . . . . . . . . . 593
52.11 Bookshop Services Listing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 594
52.12 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 596

Part XI Data Science: Data Analytics and Machine Learning


53 Introduction to Data Science . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601
53.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601
53.2 Data Science . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601
53.3 Data Science Tools and Techniques . . . . . . . . . . . . . . . . . . . . . . . . 602
Contents xxix

53.4 Data Analytics Process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 604


53.5 Python and Data Science . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 606
53.6 Machine Learning for Data Science . . . . . . . . . . . . . . . . . . . . . . . . 607
53.7 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 608
54 Pandas and Data Analytics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 611
54.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 611
54.2 The Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 611
54.2.1 The UK Government COVID Data Set . . . . . . . . . . . . . 611
54.2.2 The Google Mobility Data Set . . . . . . . . . . . . . . . . . . . . 613
54.3 Python Pandas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 614
54.3.1 Pandas Series and DataFrames . . . . . . . . . . . . . . . . . . . . 615
54.4 Loading and Analysing UK COVID Data Set . . . . . . . . . . . . . . . . 616
54.5 Loading the Google Mobility Data Set . . . . . . . . . . . . . . . . . . . . . 621
54.6 Merging Two DataFrames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 622
54.7 Analysing the Combined Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . 623
54.8 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 627
55 Alternatives to Pandas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629
55.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629
55.2 Comparing Pandas 2.0.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629
55.3 Pandas 1.x v 2.x . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629
55.4 Pandas Versus Other Libraries and Tools . . . . . . . . . . . . . . . . . . . . 630
55.5 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 632
56 Machine Learning in Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 633
56.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 633
56.2 The Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 633
56.3 SciKitLearn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 634
56.4 The Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 635
56.5 Using Regression Supervised Learning Systems . . . . . . . . . . . . . 636
56.6 K-Nearest Neighbour Regressor . . . . . . . . . . . . . . . . . . . . . . . . . . . 636
56.7 Decision Tree Regressor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 638
56.8 Random Forest Regressor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 639
56.9 Summary of Metrics Obtained . . . . . . . . . . . . . . . . . . . . . . . . . . . . 640
56.10 Creating the Regressor Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 640
56.11 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 642
57 Pip and Conda Virtual Environments . . . . . . . . . . . . . . . . . . . . . . . . . . . 643
57.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 643
57.2 Virtual Environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 643
57.3 Working with Pip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 644
57.3.1 Activating a Pip Environment . . . . . . . . . . . . . . . . . . . . 644
57.3.2 Installing Modules Using Pip . . . . . . . . . . . . . . . . . . . . . 645
57.3.3 Deactivating a Pip Environment . . . . . . . . . . . . . . . . . . 646
57.3.4 Check Version of Pip . . . . . . . . . . . . . . . . . . . . . . . . . . . . 646
57.3.5 Installing Modules into a Pip Environment . . . . . . . . . 646
xxx Contents

57.3.6 Freezing Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 647


57.4 Conda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 648
57.5 Anaconda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 649
57.5.1 Installing Anaconda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 649
57.6 Working with Anaconda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 651
57.6.1 Checking the Conda Version . . . . . . . . . . . . . . . . . . . . . 651
57.6.2 Updating Conda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 651
57.6.3 Creating a Conda Environment . . . . . . . . . . . . . . . . . . . 652
57.6.4 Listing Available Conda Environments . . . . . . . . . . . . 653
57.6.5 Activating a Conda Environment . . . . . . . . . . . . . . . . . . 654
57.6.6 Deactivating a Conda Environment . . . . . . . . . . . . . . . . 655
57.6.7 Listing the Modules Loaded into a Conda
Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 655
57.6.8 Removing an Anaconda Environment . . . . . . . . . . . . . 656
57.6.9 Installing a Module into a Conda Environment . . . . . . 656
57.7 Anaconda in PyCharm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 658
57.8 Online Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 658
Chapter 1
Introduction

1.1 Introduction

I have heard many people over the years say that Python is an easy language to learn
and that Python is also a simple language.
To some extent both of these statements are true; but only to some extent.
While the core of the Python language is easy to lean and relatively simple (in
part thanks to its consistency), the sheer richness of the language constructs and
flexibility available can be overwhelming. In addition the Python environment, its
eco system, the range of libraries available, the often competing options available,
etc., can make moving to the next-level daunting.
Once you have learned the core elements of the language such as how classes
and inheritance work, how functions work, what are protocols and Abstract Base
Classes, etc. where do you go next?
The aim of this book is to delve into those next steps. The book is organised into
eleven different topics:
1. Advanced Language Features. The first section in the book covers topics
that are often missed out from introductory Python books such as slots, weak
references __init__() versus __new__() and metaclasses.
2. Computer Graphics. The book covers Computer Graphics and Computer
Generated Art in Python as well as graphical user interfaces and graphing/
charting via Matplotlib.
3. Games Programming. This topic is covered using the pygame library.
4. Testing and Mocking. Testing is an important aspect of any software develop-
ment; this book introduces testing in general and the PyTest module in detail.
It also considers mocking within testing including what and when to mock.

© Springer Nature Switzerland AG 2023 1


J. Hunt, Advanced Guide to Python 3 Programming,
Undergraduate Topics in Computer Science,
https://doi.org/10.1007/978-3-031-40336-1_1
2 1 Introduction

5. File Input/Output. The book covers text file reading and writing as well as
reading and writing CSV and Excel files. Although not strictly related to file
input, regulator expressions are included in this section as they can be used to
process textual data held in files.
6. Database Access. The book introduces databases and relational database in
particular. It then presents the Python DB-API database access standard and
one implementation of this standard, the PyMySQL module used to access a
MySQL database.
7. Logging. An often missed topic is that of logging. The book therefore introduces
logging the need for logging, what to log and what not to log as well as the Python
logging module.
8. Concurrency and Parallelism. The book provides extensive coverage of
concurrency topics including threads, processes and inter-thread or process
synchronisation. It also presents futures and AsyncIO.
9. Reactive Programming. This section of the book introduces Reactive Program-
ming using the PyRx Reactive Programming library.
10. Network Programming. The book introduces socket and web service commu-
nications in Python. It looks at both the Flask and the Django web service
libraries.
11. Data Analytics. A very hot topic for any potential Python programmer is data
analytics (and the related use of machine learning). The book concludes by
introducing these topics and there Pandas and scikit-learn (or SK-learn as it is
sometimes known) libraries.
Each section is introduced by a chapter providing the background and key concepts
of that topic. Subsequent chapters then cover various aspects of the topic.
For example, the second topic covered is on Computer Graphics. This section
has an introductory chapter on Computer Graphics in general. It then introduces the
Turtle Graphics Python library which can be used to generate a graphical display.
The following chapter considers the subject of Computer Generated Art and
uses the Turtle Graphics library to illustrate these ideas. Thus several examples
are presented that might be considered art. The chapter concludes by presenting the
well-known Koch Snowflake and the Mandelbrot Fractal set.
This is followed by a chapter presenting the Matplotlib library used for generating
2D and 3D charts and graphs (such as a line chart, bar chart or scatter graph).
The section concludes with a chapter on graphical user interfaces (or GUIs) using
the wxpython library. This chapter explores what we mean by a GUI and some of
the alternatives available in Python for creating a GUI.
Other topics follow a similar pattern.
Each programming or library-oriented chapter also includes numerous sample
programs that can be downloaded from the GitHub repository and executed. These
chapters also include one or more end of chapter exercises (with sample solutions
also in the GitHub repository).
1.2 Useful Python Resources 3

The topics within the book can be read mostly independently of each other. This
allows the reader to dip into subject areas as and when required. For example, the
File Input/Output section and the Database Access section can read independently
of each other (although in this case assessing both technologies may be useful in
selecting an appropriate approach to adopt for the long-term persistent storage of
data in a particular system).
Within each section there are usually dependencies; for example, it is neces-
sary to understand pygame library from the ‘Building Games with pygame’ intro-
ductory chapter, before exploring the worked case study presented by the chapter
on the StarshipMeteors game. Similarly it is necessary to have read the threading
and multiprocessing chapters before reading the inter-thread/process synchronisation
chapter.

1.2 Useful Python Resources

There are a wide range of resources on the web for Python; we will highlight a few
here that you should bookmark. We will not keep referring to these to avoid repetition
but you can refer back to this section whenever you need to:
• https://en.wikipedia.org/wiki/Python_Software_Foundation Python Software
Foundation.
• https://docs.python.org/3/ The main Python 3 documentation site. It contains
tutorials, library references, set up and installation guides as well as Python
how-tos.
• https://docs.python.org/3/library/index.html A list of all the built-in features for
the Python language—this is where you can find online documentation for the
various class and functions that we will be using throughout this book.
• https://pymotw.com/3/ the Python 3 Module of the week site. This site contains
many, many Python modules with short examples and explanations of what the
modules do. A Python module is a library of features that build on and expand
the core Python language. For example, if you are interested in building games
using Python then pygame is a module specifically designed to make this easier.
• https://www.fullstackpython.com/email.html is a monthly newsletter that
focusses on a single Python topic each month, such as a new library or module.
• http://www.pythonweekly.com/ is a free weekly summary of the latest Python
articles, projects, videos and upcoming events.
Each section of the book will provide additional online references relevant to the
topic being discussed.
Part I
Advanced Language Features
Chapter 2
Python Type Hints

2.1 Introduction

Python is a dynamically typed language right—well yes it is however there is a


feature known as Type Hints that allows typing information to be provided when
functions and methods are defined. These Type Hints are extremely useful and can
help a developer understand what types are expected by a function or a method and
indeed what types are likely to be returned.
Recent versions of Python, including 3.10 and 3.11, have increased the support
for Type Hints so that they are now quite usable. These can be used by analysis tools
and IDEs to help developers create more stable and reliable applications.

2.2 Pythons Type System

Many people consider Python to be an untyped programming language. However,


that is not quite true. The type system in Python can be referred to as representing
a dynamically typed programming language. That is a variable holds a value and
the type of that value is known and understood by the language. At runtime Python
checks that what you are trying to do is valid given the types involved. For example,
you can use the type() function to find out what type of thing a variable holds at
any point in time:
a_variable = 42
print(f'a_variable type = {type(a_variable)} = {a_variable}')
a_variable = 1.345
print(f'a_variable type = {type(a_variable)} = {a_variable}')
a_variable = "Hello"
print(f'a_variable type = {type(a_variable)} = {a_variable}')
a_variable = True
print(f'a_variable type = {type(a_variable)} = {a_variable}')

© Springer Nature Switzerland AG 2023 7


J. Hunt, Advanced Guide to Python 3 Programming,
Undergraduate Topics in Computer Science,
https://doi.org/10.1007/978-3-031-40336-1_2
8 2 Python Type Hints

This produces as output:


a_variable type = <class 'int'> = 42
a_variable type = <class 'float'> = 1.345
a_variable type = <class 'str'> = Hello
a_variable type = <class 'bool'> = True

Of course, as the above shows, a variable in Python can hold different types of
things at different types, hence the term dynamically typed.
As Python knows what types variables hold it can check at runtime that your
programs are valid/correct given the types involved for example in a particular oper-
ation. Thus, it is valid to add two integers together and indeed two strings together
(as this is string concatenation) but attempting to add an integer to a string will result
in a TypeError:
print(1 + 1)
print(1.2 + 3.4)
print("Hello" + "world")
print("Hello" + 1)

This code produced the following output including the TypeError:


2
4.6
Helloworld
Traceback (most recent call last):
File "/Users/jeh/temp/pythonProjects/course/main.py", line 15,
in <module>
print("Hello" + 1)
TypeError: can only concatenate str (not "int") to str

2.3 The Challenge for Python Developers

The challenge for Python developers comes when they need to understand what types
are required by, or work with, some API. As a very simple example, consider the
following function:
def add(x, y):
return x + y

What types can be used with this function?


In essence any type can be used for the parameter x that supports the plus operator
(+) with the type in y. From the above we know that integers and strings can be used,
but we can also use floating point numbers, for example:
print(add(1, 2))
print(add(1.2, 3.4))
2.4 Static Typing 9

print(add(1, 3.4))
print(add(5.5, 1))
print(add("Hi", "There"))

All of the above are valid parameters, and the output produced from the above
code is:
3
4.6
4.4
6.5
HiThere

Even custom types can be used if they implement the special __add__(self,
other) operator method, for example:
class Quantity:
def __init__(self, amount):
self.amount = amount

def __add__(self, other):


return Quantity(self.amount + other.amount)

def __str__(self):
return f"Quantity({self.amount})"

q1 = Quantity(5)
q2 = Quantity(4)
print(add(q1, q2))

The __add__() method allows the custom type (class) being defined to be used
with the add operator (‘+’). Thus this program generates the following output:
Quantity(9)

However, what was the intent of the designer of this add() function? What did
they expect you to add together? The only option in traditional Python code is for
the developer to provide some form of documentation, for example in the form of a
docstring:
def add(x, y):
"""adds two integers together and
returns the resulting integer."""
return x + y

2.4 Static Typing

Languages such as Java, C# and C are statically typed languages. That is when a
variable, object attribute, parameter or return type is defined then the type of that
element is specified statically a compile time.
10 2 Python Type Hints

Thus, an add() method on a Java class Calculator might be written as


follows:
package com.jjh;

public class Calculator {

public int add(int x, int y) {


return x + y;
}

This makes it clear to a Java programmer and to the Java compiler that the add()
method will only handle integers and will return as a result an integer type. Thus,
there is no possibility that a developer might try to add a number to a Boolean value,
etc. In fact the compiler will not even allow it!
The Java Calculator class can be used as shown below, note that this code
will not even compile if the developer tries to add two strings together. In this case
we are adding two integers together, so all is fine:
package com.jjh;

public class App {


public static void main( String[] args ) {
System.out.println( "Starting" );
Calculator calc = new Calculator();
System.out.println(calc.add(4, 5));
System.out.println("Done");
}
}

As the above program uses valid integer types with the add() method, the output
from the compiled and executed program is:
Starting
9
Done

2.5 Python Type Hints

Python’s Type Hints are more like a half-way house between traditional Python’s
lack of typing information at all and the very strict string static typing approach of
languages such as Java.
A Type Hint is additional type information that can be used with a function
definition to indicate what types parameters should be and what type is returned.
This is illustrated below:
def add(x: int, y: int) -> int:
2.6 Type Hint Layout 11

return x + y

In this case it makes it clear that both x and y should be of type int (integer
types) and the returned result will be an int. However, adding Type Hints as shown
above has no effect on the runtime execution of the program; they are only hints and
are not enforced by Python per se. For example, it is still possible to pass a string
into the add() function as far as Python is concerned.
However, static analysis tools (such as MyPy) can be applied to the code to check
for such misuse. Some editors, such as the widely used PyCharm, already have such
tools integrated into their code checking behaviour.
If you want to use a tool such as mypy instead, or in addition to that available in
your IDE, then you can install it using
pip install mypy

Or if you want to use conda/Anaconda by using


conda install mypy

You can now analyse your code by applying MyPy to a Python file, for example:
% mypy main.py
main.py:3: error: Incompatible types in assignment (expression has
type "float", variable has type "int")
main.py:5: error: Incompatible types in assignment (expression has
type "str", variable has type "int")
main.py:24: error: Argument 1 to "add" has incompatible type "str";
expected "int"
main.py:24: error: Argument 2 to "add" has incompatible type "str";
expected "int"
main.py:44: error: Argument 1 to "add" has incompatible type
"Quantity"; expected "int"
main.py:44: error: Argument 2 to "add" has incompatible type
"Quantity"; expected "int"
Found 6 errors in 1 file (checked 1 source file)

2.6 Type Hint Layout

The Python Style Guide defined by Python Enhancement Proposal 8 (PEP 8) provides
some guidance for using Type Hints, for example:
• Use normal rules for colons, that is, no space before and one space after a colon:
text: str.
• Use spaces around the = sign when combining an argument annotation with a
default value: align: bool = True.
• Use spaces around the -> arrow: def headline(…) -> str.
12 2 Python Type Hints

2.7 Type Hints for Multiple Types

Of course our add() function could work with floating point numbers as well as it
works with integers. It would therefore be useful to be able to state this in terms of the
Type Hints. Prior to Python 3.10 this could be done using a Union type, for example
Union[int, float] which while it worked was a little unwieldy. Since Python
3.10 we can use the style syntax bar ‘|’ for example int | float as shown below:
def add(x: int | float, y: int | float) -> int:
return x + y

2.8 The Self Type

Python 3.11 introduced the Self type which is defined in PEP 673. This can be used
to indicate that a method returns a reference to itself, for example:
from typing import Self

class Shape:

def __init__(self):
self.scale = 0.0

def set_scale(self, scale: float) -> Self:


self.scale = scale
return self

2.9 The Benefits of Type Hints

There are a range of benefits to using Type Hints in Python, for example:
• They help catch some errors within programs. Obviously, the biggest benefit
is that Type Hints can help developers catch certain types of problems in their
code (assuming that some form of type checker is used).
• They provide documentation. Type Hints can also act as a level of document
that editors such as IDEs can pick up and display to other developers.
• They can be work with IDEs. They can help with code generation and IDE
auto-complete functionality.
• They can make developers stop and think. They can help ensure that developers
think about their code and what types should be supported.
• They can improve understanding of libraries. Although Type Hints may offer
little advantage in a single use script, or throw away program, they can be of
significant benefit when a library is being created. Such libraries will be used
2.11 Online Resources 13

by a range of different developers, and some may be released into the wild, for
example via PyPI, the Python Package Index. The use of Type Hints can greatly
enhance others understanding of the APIs provided by these libraries.

2.10 Summary

If you are just starting out with Python, or you are writing scripts that will only be used
once, then Type Hints may not be particularly useful. However, if you are creating
libraries or developing larger more complex applications with teams of developers,
then they can be very useful indeed.

2.11 Online Resources

• https://docs.python.org/3.10/ Python 3.10 documentation.


• https://docs.python.org/3.11/ Python 3.11 documentation.
• https://en.wikipedia.org/wiki/Type_system Wikipedia Type System page.
• https://en.wikipedia.org/wiki/Dynamic_programming_language Dynamically
typed languages.
• https://docs.python.org/3/library/exceptions.html Exception handling in Python.
• https://www.pythontutorial.net/python-basics/python-type-hints/ Tutorial on
Python Type Hints.
• https://pypi.org/project/mypy/ MyPy static type hint analysis tool.
• https://mypy.readthedocs.io/en/stable/ MyPy documentation.
• https://www.jetbrains.com/pycharm/ PyCharm IDE tool.
• https://peps.python.org/pep-0008/ Python (PEP 8) Style Guide including guid-
ance of how to layout Type Hints.
• https://peps.python.org/pep-0673/ Information on the Self type.
• https://pypi.org/ The Python package Index PyPi.
Chapter 3
Class Slots

3.1 Introduction

Python classes are very flexible, they allow data and behaviour to be defined when
the class is created, but also dynamically at any point in the lifetime of the class and
its instances. This technique is known as Monkey Patching and can be extremely
useful. However, in other situations, allowing the data or behaviour of a class to
change dynamically after the class has been defined, might be very confusing and
make the system harder to maintain. The issue is that a class’s attributes can be added
at any time, and there is no formal specification of the attributes—that is until we
look at slots. Slots allow us to specify what attributes a class will have and to ensure
that those attributes and only those attributes are used with the class and its instances.
This chapter introduces Python class slots.

3.2 The Problem

In many object-oriented languages it is necessary to define the attributes or fields


that a class will have explicitly within the class definition. For example, in Java we
might write the following:
public class Person {
private int age = 0;
private String name = "";

public Person (name String, int age) {


this.name = name;
this.age = age;
}
public int getAge () {
return age;

© Springer Nature Switzerland AG 2023 15


J. Hunt, Advanced Guide to Python 3 Programming,
Undergraduate Topics in Computer Science,
https://doi.org/10.1007/978-3-031-40336-1_3
16 3 Class Slots

}
public void setAge (int newAge) {
age = newAge;
}
public String getName () {
return name;
}
public void birthday () {
int oldAge, newAge;
oldAge = getAge();
System.out.println("Happy birthday " + getName());
System.out.print("You were " + oldAge);
System.out.print(" but now you are ");
this.age = this.age + 1;
System.out.println(age);
}
}

In the above class the two lines:


private int age = 0;
private String name = "";

declare that the Java class Person will have two attributes (also known as instance
variables in Java) called name and age. It cannot have any dynamically added
additional attributes, and it is not possible to create on the fly within a method.
The equivalent class definition in Python might look like:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age

def birthday(self):
print(f'Happy birthday {self.name}',
f', you were {self.age}',
end = '')
self.age = self.age + 1
print(f' but now you are {self.age}')

This does essentially the same thing (although in a more concise format). Using
this class we can create instances of the class and print out the details associated with
the object, for example:
p1 = Person('Phoebe', 25)
print(f'p1: {p1.name} {p1.age}')

which produces:
p1: Phoebe 25
3.3 Slots to the Rescue 17

However there is nothing to stop us adding a new attribute address to the class,
for example:
p1.address = '10 High Street'
print(f'p1.address: {p1.address}')

When we run this we get:


p1.address: 10 High Street

This is not possible in Java as address was not defined within the scope of
the class and thus objects of class Person in Java can never have any additional
attributes such as address.
In Python not only is this legal, it is also sometimes quite useful.
However, how do you know that there is an attribute address on the object in
p1? Only be reading through the code using p1, you cannot see it by looking at the
Python class definition for Person.
Perhaps even more confusingly if we write:
p2 = Person('Gryff', 24)
print(f'p2: {p2.name} {p2.age}')
print(f'p2.address: {p2.address}')

That is we create a new instance of the class Person and try to access the
attributes name, age and address (which apparently all work for the instance in
p1), and we will raise a runtime AttributeError, for example:
p2: Gryff 24
Traceback (most recent call last):
File "/person.py", line 19, in <module>
print(f'p2.address: {p2.address}')
^^^^^^^^^^
AttributeError: 'Person' object has no attribute 'address'

This indicates that the Person object in p2 does not possess an attribute
address yet p1 did! Of course this is because we added the attribute only to
the object in p1 not to the class in general.
This can be very confusing and make maintaining code much more difficult!

3.3 Slots to the Rescue

There is a special class attribute called __slots__ which can be used to provide a
sequence of strings that define or specify the attributes that the class will hold. It is
a class attribute as it is part of the class not part of an instance of object of the class.
However, it defines the attributes any instance of the class can use.
Thus if an attribute is not included in the slots sequence then it cannot be defined
within the class. This means that to find out what attributes a class defines for its
objects all you have to do is look at the slots attribute and they will be listed there.
18 3 Class Slots

It also means that it is not possible to dynamically monkey patch a class with
additional attributes at runtime.
As an example, see the modified definition for the class Person below:
class Person:
__slots__ = ['name', 'age']

def __init__(self, name, age):


self.name = name
self.age = age

def __repr__(self):
return f'Person({self.name} is {self.age})'

This version of the class Person lists the attributes name and age in the _
_slots__ class attribute. Note that the names of the attributes are defined as
strings—so don’t forget the quotes around each attribute.
Then within the class an initialiser sets up the values for the attributes
self.name, self.age, etc.
We can now create an instance of this class and for example print out the age, the
name and use the __repr__() method to convert the object to a string for printing
purposes:
p1 = Person('Phoebe', 25)
print(p1)
print(f'p1: {p1.name} {p1.age}')

The output from this is:


Person(Phoebe is 25)
p1: Phoebe 25

So far so good, but what has this given us over the original version?
If we now try to dynamically add an attribute such as address to this version
of Person, for example:
p1.address = '10 High Street'

We will now generate a runtime AttributeError indicating that the object


does not have an attribute address, for example:
Traceback (most recent call last):
File "main.py", line 16, in <module>
p1.address = '10 High Street'
^^^^^^^^^^
AttributeError: 'Person' object has no attribute 'address'

We have now fixed the attributes defined within the class to be name and age
and only ever name and age.
3.4 Performance Benefits 19

This is actually true even if we tried to define an additional attribute within the
initialiser method, for example, in the following version of the Person class has
added the self.address attribute within the __init__() method:
class Person:
__slots__ = ['name', 'age']

def __init__(self, name, age):


self.name = name
self.age = age
self.address = None

def __repr__(self):
return f'Person({self.name} is {self.age})

When we try and use this class to create a new instance of the class Person we
again get an AttributeError raised:
Traceback (most recent call last):
File "main.py", line 13, in <module>
p1 = Person('Phoebe', 25)
^^^^^^^^^^^^^^^^^^^^
File "main.py", line 7, in __init__
self.address = None
^^^^^^^^^^^^
AttributeError: 'Person' object has no attribute 'address'

Thus we are guaranteed that the class Person and all instances of the class
Person, all work with just the name and age specified in the __slots__ class
attribute.

3.4 Performance Benefits

There are in fact additional benefits to be had from using the __slots__ class
attribute. These benefits relate to performance. This is because attributes defined
using slots are more efficient in terms of memory space and speed of access and a
bit safer than the default Python method of data access.
By default, when Python creates a new instance of a class, it creates a
__dict__ attribute for the class. The __dict__ attribute is a dictionary whose
keys are the variable names and whose values are the variable values. This allows
for dynamic variable creation but can also lead to uncaught errors.
The fact that under the hood a simple dict is used for attribute storage and lookup
as a few implications:
• Dictionaries are memory expensive objects. While this may not be a problem for
a small class or for a class with only a few instances it can become far more
significant with millions of objects as they will use a lot of memory.
Random documents with unrelated
content Scribd suggests to you:
"I think you ought to know that isn't my name."

"What is it, then?"

"Mrs. Connor."

"Mrs. Connor? Missis Connor?"

"Yes."

He came down into the room. His glance traveled rapidly to the four
corners, like a wild animal dodging men and dogs. He had one question left,
one chance of escape.

"Are you a widow?" he said.

"No, a married woman."

Stevens went slowly out of the door without replying. The woman whom
he loved belonged to another man. It was like the end of the world.

VIII
THE LIFE FORCE

If Mason had been in the jeunesse dorée he must now have gone to
Monte Carlo to buck the tiger or to India to shoot him.

As it was, he smoked all night and turned up at the office half an hour
ahead of time in a voluble, erratic mood, brought about by suppressing so
much excitement within himself. If he had known how to tell his troubles to
a friend over a glass of beer he might have had an easier time of it in his
life. But he wasn't that sort. He took things hard and kept them in.
He decided that the best thing to do with his sentiment for Georgia was
to strangle it. Whenever he caught himself thinking of her, which would
certainly be often at first, he must turn his mind away. He must avoid seeing
her; if they met accidentally he would give no further sign than a curt nod.

He remembered the farmers used to say that there was one thing to do
with Canada thistles—keep them under, never let the sun shine on them.
His love for this other man's wife was like a thistle. He must keep it under,
never let the sun shine on it.

He did it thoroughly. He nodded to her in the most indifferent way in the


world when they happened to meet, but he found no occasion to stop at her
desk to chat an instant. Two weeks of his change of manner began to pique
her. He was acting in a rather absurd way, she thought. After all they weren't
lovers who had quarreled, but simply acquaintances, friends after a fashion,
fellow workers. Why shouldn't they continue to be friends? It would be
amusing to have some one besides the family and the girls to talk to.

She would not let him treat her in this stiff way any longer, just because
she had had the bad luck to marry a bad man years before. What rubbish
that was. And what self-consciousness on his part. Men had a very guilty
way of looking at things.

They met quite or almost quite by accident in front of the office building
during the noon hour of the following day. He was about to pass without
stopping.

"How do you do, Mr. Stevens?" Her voice was quite distinct.

So he turned and lifted his hat. "How do you do!"

She did not precisely move toward him, but she did so contrive the pause
that it was up to him, if he weren't to be boorish, to stop for a moment and
speak with her.

She threw a disarming candor into her first question. "Is there any
particular reason," said she, "why we are no longer friends?"
"Friends?"

"Yes. You've been frowning at me for about three weeks and I haven't the
least idea how I've offended you."

He did not answer immediately and his expression hardened.

"There, you're doing it now," said she with apparent perplexity. "Why?"

"You know," he spoke doggedly.

"No, I don't."

"Yes you do, too," he answered curtly and roughly. "You do."

"Just as you please." She turned from him, apparently offended by his
tone, slightly nodded and walked slowly away. She was of medium height,
no more than that, and slender. A brute of a man bumped her with his
shoulder as he passed her.

Stevens waited for the brute of a man, dug his elbow into his ribs and
overtook her at the Madison Street corner.

"Miss—Mrs. Connor, I didn't mean to be rude."

"You were a little, you know."

"Will you excuse me?"

"Why, of course."

He didn't quite know what to do next, so he awkwardly extended his


hand. She took it with a man-to-man shake of wiping out the score, which
completely demolished his cynical attitude in reference to platonic
friendship.

"Where were you bound for?" he asked.

"Nowhere, just strolling. Over to the lake front for a breath of air."
"May I walk along?"

"Surely."

On their way back they reflected that they had been without lunch, so
they stopped at a drug store for a malted milk with egg, chocolate flavor,
nutmeg on top.

They touched their glasses together.

"It's very nourishing," said he with wonderment.

"Very," she replied, delightedly; "very."

They returned to their work in that state of high elation induced by


interviews such as theirs, wherein the spoken words mean twenty times
what they say—and more.

IX
THE PRETENDERS

Georgia and Mason did not overpass the outward signs and boundaries
of platonism, learning to avoid not merely evil, but the appearance of evil.
When they met in the hundred-eyed office they were casual.

During the autumn they took long walks together every Sunday. There
had been a dry spell that year, lasting with hardly a break from the fore part
of June, which baked the land and sucked out the wells and put the
Northern woods in danger of their lives. The broad corn leaves withered
yellow and the husbandmen of the great valley protested that the ears were
but "lil' nubbins with three inches of nuthin' at the tips, taperin' down to a
point, and where'll we get our seed next spring?"
When the huge downpour came at last and by its miracle saved the crop
which had been given up for lost a fortnight since, Mason cursed the day,
for it fell on the first day of the week and cost him, item, one walk and talk
with Georgia Connor. She stood so near his eyes as to hide from his sight a
billion bushels parching in the valley—though he was country bred.

To her their Sundays together brought not a joy as definite as his, but
rather a sense of contentment, of relief from the precision of the other days
of her week. It pleased her to wander to the big aviary and look at the
condors and cockatoos and wonder about South America where they came
from, then to stroll slowly over to the animals and have a vague difference
of opinion with him about whether a lion could whip a tiger.

She thought so because the lion was the king of beasts, but Mason didn't,
because he'd read of a fight where it had been tried. Once he even grew a
trifle heated because she wouldn't listen to reason and fact and stuck to the
lion because he'd been called the king of beasts, whereas all naturalists
knew the elephant and the gorilla and the rhinoc—— There she interrupted
him with a laugh and called him a boy and too literal.

Every Sunday they had this same dispute until finally they both learned
to laugh about it and made it a joke between them, and she told him he was
doing much better. They walked by the inside lake and wondered if the wild
ducks and geese on the wooded isle liked to have to stay there, and they
took lunch when they got good and ready, perhaps not until two or three or
even four o'clock in the afternoon.

She always went home for supper, but often she came out again
afterwards, and took the car down town to a Sunday Evening Ethical
Society which foregathered in an old-fashioned theatre building.

There was almost always some well-known speaker whose name was
often in the papers, perhaps a professor or a radical Ohio Mayor or a labor
lawyer, to address them on up-to-date topics like Municipal Ownership in
Europe or the Russian Revolution or the Androcentric World, which showed
women had as much right to vote as men, or non-resistance, a kind of
Christianity that wasn't practical. Stevens didn't like that lecture much.
Jane Addams spoke once about the children that lived in her
neighborhood. He thought her talk the best of all; so did Georgia. He said to
her that Jane Addams was as much of a saint as any of those old-timers that
were burnt and pulled to pieces and fed to lions, and a useful kind of a saint
as well, because she helped children instead of just believing in something
or other. Georgia didn't answer his remark at the time, but nearly half an
hour later as she was bidding him good night she had him repeat it to her,
and the next day she told him that what he had said about Miss Addams was
very interesting.

They had organ music at these meetings and a collection, so that he felt
it was the next thing to going to church. But Georgia in arguing out the
matter with herself concluded that there was so little religion in the services
that in attending them she violated the Church's law against worshiping
with heretics hardly more than if she went to a political meeting. She would
never go to a regular Protestant service with Mason, even if he asked her.
She made up her mind firmly on that point. So perhaps it was as well he
didn't ask her.

Her waking memories of Jim were now much fainter and dimmer. She
tried not to think of him at all. She refused to let her mother or Al speak his
name or make allusion to him. At the beginning, just after his departure,
mama had harped on the subject until she thought it would drive her crazy.

Over and over and over again she traversed the same ground—about his
being her husband, and Christian charity, and one more trial, and the
disgrace of it, and that it was the first time such a thing ever happened in the
family.

Finally in self-defense and to save herself from being upset every night
when she was tired and worn out anyway, she told her mother that the next
time she mentioned Jim's name she would leave the room. And she only had
actually to do this three times before poor mama succumbed, as she always
did when she was met firmly. However, she still managed to say a volume
in Jim's favor with her deep sighs and her "Oh, Georgia's," but Georgia
always pretended she didn't know the meaning of such signs and
manifestations. Of course, especially at the beginning, her husband's face
often came unbidden between her and her page, but she gathered up her will
each time to banish it again, and it's surprising what a woman can do if she
only makes up her mind and sticks to it.

But her dreams were the trouble. Jim would enter them. She didn't know
how to keep him out. And he always came, sometimes two or three nights
in succession, to bring her pain.

She usually appointed her Sunday rendezvous for an hour before noon at
Shakespeare's statue in the Park, and sailed off cheerily in her best bib and
tucker to meet Mason, leaving behind her a fine trail of excuses, a complete
new set each week, to explain to mama why she couldn't go to mass. On
this particular morning she said she had a date with a girl-friend from the
office.

With the best intention in the world she was never on time and always
kept him waiting. She was so unalterably punctual for six days a week that
the seventh day it was simply impossible.

Stevens usually became slightly irritated during these few minutes—


what business man wouldn't?—and referred to his watch at hundred-second
intervals, determined to ask her once and for all why she wasted so much
time in tardiness. But when finally he distinguished her slim little figure in
the Sunday throng that was streaming toward him, his impatience left not a
wrack behind.

They started gayly northward, bantering each other in urban repartee. As


they passed gray Columbus Hospital their mood swerved suddenly and they
talked of sickness and death and immortality.

Her belief was orthodox, but it did not hold her as vividly as it held the
old folk in the old days. Had she lived nearer to the miracles of the sun
going down in darkness and coming up in light; or thunderstorms and
young oats springing green out of black, with wild mustard interspersed
among them like deeds of sin; of the frost coming out of the ground; and the
leaves dying and the trees sleeping; she would perhaps have lived nearer to
the miracles of bread and wine, of Christ sleeping that the world may wake.
But she lived in a place of obvious cause and effect. When the sun went
down, the footlights came up for you if you had a ticket, and man's miracle
banished God's even though you might be in the flying balcony and the
tenor almost a block away. Thunderstorms meant that it was reckless to
telephone; oats, wheat and corn, something they controlled on the board of
trade; the melting of the snows showed the city hall was weak on the sewer
side—what else could you expect of politicians?—the dying leaves
presaged the end of the Riverview season and young Al's excitement over
the world's series.

Living in the country puts a God in one's thoughts, for man did not make
the country and its changes, yet they are there. Farmers pray for rain or its
cessation according to their needs. To live in the city is to diminish God and
the seeming daily want of Him, for man built his own city of steel and
steam and stone, unhelped, did he not?

God may have made the pansies, but He did not make "the loop." His
majesty is hidden from its people by their self-sufficing skill, and they turn
their faces from Him. West-siders do not pray for universal transfers.

Never had Georgia questioned her faith. Its extent remained as great as
ever. She had consciously yielded no part of her creed. But its living quality
was infected by the daily realism of her life, as spring ice is honeycombed
throughout with tiny fissures before its final sudden disappearance.

So she talked to Stevens of her convictions, but in a calm dispassionate


way, without emotional fervor.

Stevens' great-grandparents whenever they referred to the Romanist


Church, which was often, spoke of "the scarlet woman" or "the whore of
Babylon." His grandparents, products of a softer, weaker generation,
stopped at adjectives, "papist," "Jesuitical," "idolatrous."

His parents receded still further from the traditions of the Pilgrims.
Indeed his father, being a popular horse doctor, kept his mouth shut
altogether on the subject, and his mother seldom went beyond remarking
that there was considerable superstition in the Catholic service and too
much form to suit her.
As for the son himself, he could as soon have quarreled about the rights
and wrongs of the Mexican war as he would about religion. He wasn't
especially interested in either. He thought there was a lot of flim-flam for
women in all religion, especially in Catholicism. But it was an amiable
weakness of the sex, like corsets. So he let Georgia run on, explaining her
faith, without interruption.

Then most wretched luck befell them. Georgia looked up from the tips of
her toes, being vaguely engaged, as she talked, in stepping on each large
pebble in the gravel path and her eyes rested squarely upon her mother.
Mrs. Talbot mottled; Georgia blushed.

All progress was temporarily arrested; then the older woman puffed out
her chest and waddled away with all the dignity at her summons. But she
could not resist the Parthian shot—what Celt can!—and she turned to throw
back over her shoulder, "Who's your girl-friend, Georgia?" Her teeth
clicked and she continued her departure.

Stevens realized that there had been a contretemps of some sort and that
it was his place, as a man of the world, to laugh it off.

"Who's the old pouter pigeon?" he inquired.

"Mama."

"Oh!"

Feeling that candor was now thrust upon her, Georgia proceeded to
explain to Stevens that she had never explained about him to her mother, for
mama couldn't possibly understand, being old-fashioned and prejudiced in
some regards.

"So you've made me fib for you," she finished. "Aren't you ashamed!"

"Yes," said he, in truth much gratified by her clandestineness.

"But what I don't see is——," he began, then broke off.

"Is what?"
"Is why you should be so disturbed about your mother's knowing."

"I've told you—for the sake of peace and a quiet life."

"But what about your husband?" He blurted it out suddenly, the word
which had crucified him since his one and only visit to her home; the word
which he had kept dumb between them until now. "What about him?
Doesn't he mind?"

"He left me six months ago. You never supposed I would take a man's
bread and—fool him, did you, Mason?" She called him by his name for the
first time.

"I didn't know," he muttered, "I've been to hell and back thinking of it."

"How did you suppose it would come out?" she asked, fascinated
objectively by the drama of her life.

"I felt we were playing bean-bag with dynamite—and we ought to quit


—made up my mind—while I was waiting for you this morning to tell you
this must be the last time, because we were drifting straight into——" He
paused.

"Into what?" There was a touch of gentlest irony in her tone.

"Into trouble, lots of it." There was a touch of apology in his.

"And you didn't want trouble, lots of it?" Her irony was not less. "At
least not on my account?"

"I was thinking of what would be best for all of us. I was trying to do the
square thing—the greatest happiness for the greatest number." There was a
pause, unsympathetic. "Wasn't that right?" he ended with no great
confidence.

"Why, of course, perfectly right," she assented heartily. "It shows


consideration. You considered the case systematically from all sides. Yours,
and mine, and my husband's, and the rest of the family's, and the rest of
yours, too, I suppose, didn't you?" She looked extremely efficient and spoke
in her business voice with a little snap to her words.

She was quite unfair in taking this tack with unhappy Stevens, who,
however often he thought of his duty in these twisted premises, would
surely not have done it if she beckoned him away. For she owned the only
two hands in the world which he wanted to hold.

A woman, however, prefers to be the custodian of her own morals and it


gratifies her at most no more than slightly to find that her lover has been
plotting with himself to preserve her virtue. It is for the man to ask and for
her to deny, sadly but sweetly—and she doesn't care to be anticipated.
Especially when she is self-perceptibly interested.

"But since you are already separated from——"

"Yes, that makes it pleasanter all around, doesn't it?" she led him on most
treacherously.

"Why, of course—that's what I was saying," he blundered. "Now I can


ask you to——"

"Mason, I've a frightful headache, the sun perhaps—and I think I will go


home and lie down, if you don't mind."

He looked up in some amazement at the lord of day half hidden by the


haze in his November station, and it suddenly occurred to him that woman
is a various and mutable proposition always.

"What's the matter with you, anyway?"

"Nothing," she responded with deliberate unconvincingness, "nothing in


the world, but a headache." She held out her hand. "Don't bother to come
with me. We might be seen. Good-bye." And she was off.

It was a winding gravel path and she was lost behind a curving hedge
before he started in pursuit. She quickened her pace when she heard his step
behind and it was almost a walking race before he overtook her.
"Georgia," he exclaimed, somewhat ruffled by her unreasonableness.
She neither turned her head nor answered.

"Georgia!" he repeated more loudly. Then he took her wrist and forcibly
arrested her.

"Please let me go," she requested with supreme dignity, "you are hurting
me."

"Not until you hear what I have to say. Will you marry me?"

"Marry you?" She dropped her eyes before his frowning ones. The
shoulders which had been thrown so squarely back seemed to yield like her
will and drooped forward into softer lines.

"Yes," he tightened his hold on her wrist, "will you?"

"I am a Catholic."

"But isn't there some way around that?" Your man of business believes
there is some way around everything.

"No. Divorce and remarriage aren't permitted to us."

"Don't they ever annul a marriage?"

"Not if it has been marriage." A look of misery came over his face. She
perceived it and went steadily on. "I had a child once—that died."

He dropped her hand, unconsciously to himself, but she felt it as a clear


signal between them.

"You see how little you have known me," she said softly. "Poor old
fellow, I'm sorry. Too bad it had to end like this." Her eyes were now
swimming in tears which she did not try to conceal. "Don't you see, dear,
that is why I kept putting off telling you things about my affairs, and why I
had tried to keep it—friendship, because I knew when we came as far as
this we would have to stop."
"It will never stop," he said tensely, "never."

Response seemed to sweep through her suddenly, bewildering her by its


unexpected strength.

"Perhaps not," she assented slowly, "if—if we—dare."

"Georgia," he pleaded, "you know that I——"

"Yes," in a whisper, "I know."

"And do you care, too?"

She looked up, and her answer was plain for him to read.

"More than you will ever know, Mason," she said.

"Georgia, are you a devout Catholic? Does it mean all of life to you here
and hereafter?"

"No, not very devout. Nothing like mother, for instance. I have grown
very careless about some things."

"Would you always be governed by the teaching of the Church in this


matter—always—never decide for yourself?"

"When it came to such a big thing," she said slowly, "I don't think I'd
dare disobey."

"What are you afraid of—future punishment?"

"Why, yes, partly that," she smiled; "it isn't a very jolly prospect, you
know."

He was truly astonished. He supposed that everybody nowadays, even


Catholics, had tacitly agreed to give up hell. Hell was too ridiculously
unreasonable to be believed in any more.

"Georgia," he asked, "have you ever looked much at the stars?"


"Why, yes; once in awhile. Last Sunday evening at Bismarck Garden Al
and I found the dipper—it was just as plain—is that what you mean? Of
course I don't pretend to be much of an astronomer."

"Some nights," he said, "when it's clear I go up on the roof and lie on my
back, and, well, it's a great course in personal modesty. Some of those stars,
those little points of light, are as much bigger than our whole world as an
elephant is bigger than a mosquito, and live as much longer."

"Of course," she answered, "we know that everything is bigger than
people used to think, but still couldn't God have made it all, just the same?"

"Do you honestly believe," he rejoined, speaking very earnestly, intent


on shaking her faith, if that were possible, "that Whoever or Whatever was
big enough to put the stars in the sky is small enough to take revenge
forever on a tiny little molecule like you—or me? Do you honestly suppose
that after you are dead, perhaps a long time dead, this mighty God will hunt
for you through all the heavens, and when he has found you, you poor little
atom of a dead dot, that he will torment and pester you forever and ever
because you had once for a space no longer than the wink of an eye acted
according to the nature he gave you? If that is your God, he has put nothing
in his universe as cruel as Himself."

She frowned in a puzzled way for a few seconds, looking at him with an
odd little wide-eyed stare, then shook her head slowly.

"Yes," said he in answer. "Some day you will take your life in your own
hands and use it. You're not the stuff they make nuns out of. There's too
much vitality in you.

"How old are you?" he asked suddenly.

"Twenty-six."

"Twenty-six and ready to quit? I don't believe it."

"You don't understand, Mason," she answered, "you can't. You're not a
Catholic. Catholicism is different from all other creeds. It is not just
something you think and argue about, but it has you—you belong to it; it is
as much a part of you as your blood and bones." There was a finality in her
voice, a resignation of self, which bespoke the vast accumulated will of the
Church operating upon and through her.

Stevens knew suddenly that she was not an individualized woman in the
same sense that he was an individualized man, with the private possibility
of doing what he pleased so long as he did not interfere with the private
possibilities of others; he realized that in certain important intimate matters
such as the one which had arisen between them she was without power of
decision, the decision having been made for her many centuries ago; and he
felt the awe which comes to every man when first he is confronted by the
Roman Catholic Church.

"You mean there is no way out of it—but death?—your husband's


death?" His self-confidence seemed to have departed as if he, too, had met
fate in the road.

"Yes," she answered gently, "that is the only way." And then she smiled
with some little effort, but still she smiled, for she detested gloom on her
day off. "Oh, Mason," said she, "why wasn't grandpa a Swede?"

He looked at her with amazement and not without a trace of


disapprobation, for her eyes were dancing. Was she actually making jokes
about his misery—to say nothing of hers—if indeed she felt any? He was
learning more about women every minute.

Now she was practically giggling. He frowned deeper and sighed.


Perhaps, perhaps everything was for the best, after all. He might as well tell
her so, too. No reason to make himself wretched for something she seemed
to think hilariously humorous.

"Well, Georgia, I must say," he began portentously—'twas the voice of


the husband—almost. She could hear him complain. Whereat she simply
threw back her head and laughed again.

He noticed, as he had often noticed, that her strong little teeth were white
and regular, that her positive little nose was straight and slender, and the
laughter creases about her eyes reminded him of the time she thought it
such fun to be caught in Ravinia Park in the rain without an umbrella.

So presently he tempered his frown, then put it away altogether, and his
eyes twinkled and he turned the corners of his mouth up instead of down.

"Oh, dear me," he mocked, half in fun and half not, "as the fellow says,
'we can't live with 'em and we can't live without 'em.'"

But she, who had been reading him like a book in plain print, asked,
"Come, tell aunty your idea of a jolly Sunday in the park with your best
girl. To sit her on a bench and make her listen while you mourn for the
universe?"

"But what are we going to do about it?" he asked solemnly, "that's what I
want to know."

"Do?" she responded with a certain gay definiteness, "do nothing."

"You mean not see each other any more at all?" he asked desperately. "I
absolutely refuse."

"No, silly, of course I don't mean that. We'll go on just as before, friends,
comrades, pals."

"When we love each other—when we've told each other we love each
other?"

"Certainly. What's that got to do with it?"

"It would be the merest pretense," he declared solemnly.

"Then let's begin the pretense now, and go up and throw a peanut at the
elephant. Come along." She hooked her arm into his. Her levity of behavior
undoubtedly got past him at times.

"Georgia"—he was once more on the verge of remonstrance—"if you


cared as you say you do, if you loved me as I l——"
She unhooked her arm and now she was serious enough.

"Don't you understand," she said, "what I mean? We can't talk about that
any more."

"You mean not at all?"

"Precisely."

"But what if I can't conceal the most important thing in my whole life?
What if I can't smirk and smile about it? What if I am not as good an actor
as you? What if I can't pretend? What then?" He was very, very fierce with
her.

"Then I suppose I'll have to go home." They stood irresolute, facing each
other, neither wishing to carry it too far.

"Not that that would be much fun—— Oh, come, don't be silly—let's go
attack the elephant. What must be, must be, you know."

She paused to allow him time to yield with grieved dignity, then she
headed for the animal house; he trailed in silence about half a step behind
her during the first hundred yards, but finally sighed and surrendered and
then fell into step and pretended during the rest of the afternoon with quite
decent success.

So his education began. And though he was by no means pliable


material, she managed, being vastly the more expert, to keep him
pretending with hardly a lapse throughout the winter.

She found it more difficult, however, to keep herself pretending.

X
MOXEY
Moxey was a Jew boy and a catcher. His last name ended in sky, and he
came from the West-side ghetto. His father and mother came from the pale
in Russia when Moxey's elder brother Steve was in arms and before Moxey
himself appeared.

Moxey would have been captain of the Prairie View Semi-Pro. B. B.


Club, if merit ruled the world. But there was the crime of nineteen centuries
ago against him, so they made McClaughrey captain; Georgia's sixteen-
year-old brother Al played third base.

The Prairie Views had one triumph in the morning, it being Sunday, the
day for two and sometimes three games. They had the use of one of the
diamonds on a public playground from Donovan, the wise cop.

I have seen Donovan keep peace and order among eighteen warring lads
from sixteen to twenty years old by a couple of looks, a smile and a silence.
When there was money on the game, too.

There has been good material wasted in Donovan. Properly environed


and taught the language, though he doesn't depend on language very much,
he could have been presiding officer of the French Chamber of Deputies—
and presided.

It was the ninth inning, last half, tie score, two out, three on, with two
and three on the batter. In other words, the precise moment when the
fictionist is allowed to step in. Moxey up.

He fouled off a couple, the coachers screeched; the umpire, who was
also stakeholder, dripped a bit freer and hoped Donovan would stick around
for a few seconds longer.

The pitcher took a short wind-up and the ball, which seemed to start for
the platter, reached Moxey in the neighborhood of the heart. He collapsed.
They rallied round the umpire.

"He done it on purpose—the sheeny—he done it on purpose, I tell you—


he run into it——"
"Naw, ye're a liar!"

"Prove it."

"It's a dead ball—take your base—come in there, youse," waving to the


man on third.

"We win. Give us our money."

All participated but Moxey, who lay moaning on the ground by the home
plate.

Donovan strolled out to the debate and smiled his magic smile. "Take yer
base," bawled the emboldened ump, and waved the run in. Al got five
dollars for the day's playing and three dollars for the day's betting, and the
Prairie Views walked off, bats conspicuous on shoulders, yelling, "Yah!" at
the enemy.

"Chee," said Moxey to his playmates when they reached the family
entrance, "me for the big irrigation." And it was so.

Moxey shifted his foot, called his little circle around him close and then
inserted his dark, fleshless talon into his baseball shirt. "That gave me an
awful wallop what win the game," he said; "if I hadn't slipped me little pad
in after the eight', it might a' put me away, understand." He took out his
protection against dead balls, an ingenious and inconspicuous felt
arrangement to be worn under the left arm by right-handed batters. And all
present felt again that there had been injustice in the preference of
McClaughrey.

Whenever they asked Moxey where he lived, he answered, "West," and


let it go at that. He always turned up for the next game, no matter how often
plans had been changed since he had last seen any of them. That was all
they knew about him. He caught for them, often won for them, drank beer
with them and then disappeared completely until the next half-holiday.

Perhaps Al was his most intimate friend, and Al was the only one who
learned his secret. "Say, Al," he blurted out almost fiercely one evening,
"your folks is Irish, ain't they?"

"Irish-American," corrected Al.

"Well, mine's Yiddishers, and the most Yiddish Yiddishers y'ever see."

Moxey seemed very bitter about it and Al waited for more.

"My old man, well——" Moxey swallowed. It seemed to Al as if he


would not go on, but finally it came out with a rush. "He pushes a cart—
yes, sir—honest to God, he pushes a cart—I thought maybe I ought to tell
you, Al."

"He does?" It was a shock to the Irish-American, which showed in his


tone.

"Yes, sir, he does," Moxey answered defiantly, "and if you don't like it—
why—well, I won't say nuthin' ugly to you, Al—you're only like the rest.
S'long."

Al threw his arm around the other's shoulder. "Forget it, Moxey." Which
was the only oath ever taken in this particular David and Jonathan affair.

Not long afterwards, Moxey proposed to Al attendance at a prizefight


just across the State line, the Illinois laws being unfavorable to such
exhibitions of manly skill or brutality, whichever it is. It was Al's first fight.

They boarded a special train, filled with coarse men bent upon coarse
pleasure. But then, if they had been bent upon refined pleasure they
wouldn't have been coarse or it wouldn't have been pleasure.

The prizefighting question illustrates well the gulf between the social
and the individual conscience and demonstrates that the whole is sometimes
considerably greater than the sum of its parts. Probably eight out of ten men
in this country enjoy seeing two hearty young micks belt each other around
a padded ring with padded gloves. But they hesitate to come out in the open
and proclaim their enjoyment, for fear of writing themselves down brutes,
and the deepest yearning of the American people at the present day is to be
gentlemanly and ladylike.

So whenever sparring matches are proposed the community works itself


up into a state of fake indignation. All the softer and sweeter elements
telegraph the Governor and if that isn't enough, pray for him; and inasmuch
as the Governor gets no immoral support on the other side from those who
are afraid of jeopardizing their gentlemanliness, he yields, and appears in
the newspapers as a strong man who dared beard the sports, whereas, he
was really a frightened politician who didn't dare beard the Christian
Endeavorers.

One of the most illuminating essays of the late and great William James
concerned Chautauqua Lake. He spent a week at that beautiful camp, where
sobriety and industry, intelligence and goodness, orderliness and ideality,
prosperity and cheerfulness pervade the air.

There were popular lectures by popular lecturers, a chorus of seven


hundred voices, kindergartens, secondary schools, every sort of refined
athletics, and perpetually running soda fountains.

There was neither zymotic disease, poverty, drunkenness, crime or


police.

There was culture, kindness, cheapness, equality, in short what mankind


has been striving for under the name of civilization, a foretaste of what
human society might be, were it all in the light, with no suffering and no
dark corners.

And yet when he left the camp he quotes himself as saying to himself:
"Ouf! What a relief. Now for something primordial to set the balance
straight again. This order is too tame, this culture too second-rate, this
goodness too uninteresting. This human drama without a villain or a pang;
this community so refined that ice cream soda is the utmost offering it can
make to the brute animal in man; this city simmering in the tepid lakeside
sun; this atrocious harmlessness of all things—I cannot abide with them."
But whether he could or not, the rest of us have to, and the country
moves Chautauqua-ward with decorous haste. From anti-canteen and anti-
racing to anti-fights and anti-tights, the aunties seem to have it, the aunties
have it, and the bill is passed.

Al viewed this national tendency with mixed feelings; with joy when he
tasted forbidden fruit and sneaked off across the state line with Moxey in a
special train full of bartenders and policemen off duty and gay brokers and
butchers to see more than the law allowed; with sorrow when he considered
the future of his country, as a gray, flat and feminine plain.

The preliminaries had been fought off; there was the customary nervous
pause before the wind-up. Young men with official caps forced their ways
between the packed crowds with "peanuts, ham sandwiches and cold
bottled beer." The announcer, a tall young man in shirt sleeves, who looked
as if he might be a fairly useful citizen himself in case of a difference, made
the customary appeal.

"Gen-tul-men, on account of the smoke in the at-mos-phere, I am


requested to request you to quit smoking." (Pause.) "The boxers find it
difficult to box in this at-mos-phere, and you will wit-ness a better
encounter if you do." (Applause, but no snuffing of torches.)

"The final contest of this evening's proceedings," called the announcer,


first to one side of the ring, then to the other, "will be between Johnny
Fiteon and Kid O'Mara, both of Chicago, fer th' bantamweight champ'nship
o' th' world."

Handclappings and whistlings. But the announcer, being gifted with the
dramatic instinct, knew how to work up his climaxes, which, so far as he
personally was concerned, would culminate with the tap of the gong for the
first round. It was his affair to have the house seething with excitement
when that gong tapped.

"Gen-tul-men," continued the announcer; then he spied two plumes


waving in the middle distance and made the amend, to delighted sniggers:
"Ladees and gen-tul-men, I take pleasure in in-ter-ducing Runt Keough of
Phil-ur-del-fy-a." A diminutive youth with a wise face stepped in the ring
and bobbed his head to the cheers, and muttered something to the
announcer. "Runt Keough hereby challenges the winner of this bout, for the
championship of th' world in the 115-poung class, to a finish." A tumult
ensued. The Runt backed out of the ring to hoots of "fourflusher" and howls
of approbation.

"Ladees and gen-tul-men, I now take pleasure in in-ter-ducing to you Mr.


Ed Fiteon, father and handler of Johnny Fiteon, who wears th'
bantamweight crown o' th' world."

The crowd made evident its vehement gratitude for Ed's share in
Johnny's creation.

"Chee," whispered Moxey to Al, as they sat close and rapt, with shining
eyes, on the dollar seats high up and far away, "they'd tear up the chairs for
Johnny's mother if they'd perduce her."

But now something was happening by the east entrance. The cheering
suddenly ceased, A low anxious buzzing whisper ran over the entire
assemblage. Men stood up to look eastward regardless of monitions from
behind to sit down. Something was cutting through the crowd from the east
entrance to the ring. It was Kid O'Mara in his cotton bathrobe preceded by a
gigantic mulatto and followed by two smaller Caucasians.

Moxey's bony fingers dug suddenly into Al's biceps. "Kid, you gotta do
it, Kid, you gotta," he whispered. "O, fer God's sake, Kid."

Al was surprised. "Are you with O'Mara?" he asked.

"Am I with him?" answered Moxey with a sob in his voice; "am I with
him—he's me cousin."

"O'Mara your cousin?"

"Lipkowsky's his right name—same as mine. Look at his beak and see."

There was no doubt of it. "Kid O'Mara's" proboscis corroborated


Moxey's claim.
Johnny's entrance a few minutes later was still more effective and his
reception warmer. Fight fans are courtiers, always with the king.

When the two boys stripped, Johnny showed short and stocky, the Kid
lank and lithe. Johnny depended on his punch, the Kid on his reach.

They fought ten rounds and it was called a draw, probably a just decision
inasmuch as the adherents of each contestant proclaimed that the referee
had been corrupted against their man.

Besides, a draw meant another fight between them with plenty of money
in the house.

This evening in fistiana was perhaps the most powerful single


experience which influenced Al at this period of his life. For a long time he
sat silent beside Moxey on the return trip, pondering the physical beauty of
Johnny and the Kid and ruefully comparing their bodies with his own.

He sighed, "And now I s'pose your cousin'll go out and kill it to-night!"

"Not him," Moxey reassured; "he never touches it in any form or shape,
understand."

"He's training all the time?" continued Al, bent on deciphering the secret
ways of greatness.

"Yep. So you might say."

"Oh," then Al relapsed into silence to wrestle with the angel of training
all the time.

Like most young fellows, Al regarded his body as the source of all the
happiness that amounted to anything. The brain was merely its adjunct, its
money maker and guide. Its operations might lead to life, but they were not
life like the body's.

It flashed upon him in the train bound home from the fight that he might
achieve joy in either of two ways, by going in for sports or "sporting," by
perfecting the animal in him or by abusing it, by getting into as good shape
as Kid O'Mara or into as bad shape as the pale waster crumpled in the seat
across the aisle.

So began a struggle in him, not yet ended, between the Ormuzd and
Ahriman of physical condition. His high achievement thus far has been
sixth place in a river Marathon swimming race, his completest failure
thirty-six successive drunken hours in the restricted district.

XI
FUSION

Al wasn't much of a head at books. Georgia persuaded him to start in


high school, but he soon came out, for he found that it interfered with the
free expression of his personality. There were too many girls about one and
he became extremely apprehensive lest he develop into a regular lah-de-
dah.

Georgia was more afraid of his developing into a regular rough and
tough, so they had a very intense time of it in the flat while the question was
under discussion.

Mother Talbot sided with neither of them. She wanted Al to continue his
instructions, but in the institutions under the direction of the Church. She
couldn't reconcile herself to Al's getting his learning in a place where the
very name of God was banned, as it was in the public schools.

Indeed in her opinion, and you couldn't change it, no, not if you argued
from now until the clap of doom, the main trouble with everything nowdays
was impiety and weakening of faith, brought about how? Why, by these
public schools, these atheist factories that were ashamed of the Saviour.

For her part, she couldn't see her son going to one of them with any
peace of mind, and she wanted them both to remember, that he would go
against her consent and in spite of her prayers. What's more, if he was
undutiful in this matter he'd probably find himself sitting between a Jew and
a nigger, which she must say would serve him right.

Did Georgia think, she inquired on another occasion, that the priests
weren't up to teaching Al, or what? To be sure, learning was a fine thing for
a boy starting out in the world and she approved of it as much as any one,
but who ever heard of an ordinary priest who hadn't more wisdom in his
little finger than a public school teacher had in her whole silly head!

In a church school he would receive instructions not only in temporal,


but also in divine learning. He would be taught not merely history and
mathematics and such like, but also goodness and pure living, which were
far more important for any young fellow.

But Georgia could not be convinced. She said she had been to a convent
and if she had it to do over again she would go to public high school—just
as Al, who not only was a considerate and loving brother, but also could see
clearly how sorry he would be in after life if he didn't, was about to decide
to do.

She finally had her way and Al picked up his burden—and found it not
so difficult to carry after all. For he joined the Alpha Beta Gammas and rose
rapidly in that order, becoming its most expert and weariless initiator, a very
terror to novitiates. But precisely at the moment when the Alpha Bets
reached the zenith of their glory, the skies fell upon them—the edict coming
from above that all fraternities must go.

Al went too. The place was indubitably fit for nothing but girls now. And
whatever Georgia might say, this time he was going to stick, for in the last
analysis she was a female and her words subject to discount.

He stuck, discounting the female; and she was distressed like a mother
robin in the tree, whose youngling, that has just fluttered down, persists in
hopping out of the long grass upon the shaven lawn, when, as all robinhood
knew, there were cats in the kitchen around the corner of the house.
It is the impulse of youth to travel far in search of marvels, a vestige, so
it is said, of the nomadic stage of human development, when the race itself
was young. It was as member of a demonstration crew for a vacuum
cleaning machine that Al enjoyed his wanderjahre. He went among strange
people and heard the babbling of many tongues without passing out of
Chicago.

Like a reporter, or a mendicant friar of old, he knocked on all doors. The


slouch, the slattern, the miser and the saint opened to him; the pale young
mother with a child at her breast and another at her skirts and both her eyes
black and blue; or the gray old sewing woman who for her plainness had
known neither the bliss nor the horror of a man. One rolling-mill husky in
South Chicago chased him down stairs with a stick of wood, and another
heaved his big arm around him and made him come in and wait while little
Jerry took the pail to the corner.

He came upon a household where one life was coming as another was
going, and a little girl of twelve who could no longer contain the excitement
of the day beneath her small bosom followed him into the entry way as he
hastily backed out, and whispered between gasps to catch her breath her
version of family history in the making.

He learned early the value of the smooth tongue, the timely bluff and the
signed contract; and grew rapidly from boy to man in the forcing-bed of the
city.

Meanwhile Moxey, not yet twenty, was swimming in a sea of sentiment.


There was a young Italian girl who worked in the paper-box factory.

"Angelica," said he, "come to the dance to-night."

"Nit," she responded.

"Why?"

"Oh, they'd give me the laugh, if I——" She paused tactfully.

You might also like