A H A N D S - O N , P R O J E C T - B A S E D I N T R O D U C T I O N T O P R O G R A M M I N G E R I C M A T T H E S P Y T H O N C R A S H C O U R S E P Y T H O N C R A S H C O U R S E

Python Crash Course

P y t h o n C r a s h C o u r s e a h a n d s - o n , P r o j e c t - B a s e d I n t r o d u c t i o n t o P r o g r a m m i n g by Eric Matthes San Francisco

Python Crash Course. Copyright © 2016 by Eric Matthes. All rights reserved. No part of this work may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording, or by any information storage or retrieval system, without the prior written permission of the copyright owner and the publisher. First printing 19 18 17 16 15 1 2 3 4 5 6 7 8 9 ISBN-10: 1-59327-603-6 ISBN-13: 978-1-59327-603-4 Publisher: William Pollock Production Editor: Riley Hoffman Cover Illustration: Josh Ellingson Interior Design: Octopod Studios Developmental Editors: William Pollock, Liz Chadwick, and Leslie Shen Technical Reviewer: Kenneth Love Copyeditor: Anne Marie Walker Compositor: Riley Hoffman Proofreader: James Fraleigh For information on distribution, translations, or bulk sales, please contact No Starch Press, Inc. directly: No Starch Press, Inc. 245 8th Street, San Francisco, CA 94103 phone: 415.863.9900; info@nostarch.com www.nostarch.com Library of Congress Cataloging-in-Publication Data Matthes, Eric, 1972- Python crash course : a hands-on, project-based introduction to programming / by Eric Matthes. pages cm Includes index. Summary: "A project-based introduction to programming in Python, with exercises. Covers general programming concepts, Python fundamentals, and problem solving. Includes three projects - how to create a simple video game, use data visualization techniques to make graphs and charts, and build an interactive web application"-- Provided by publisher. ISBN 978-1-59327-603-4 -- ISBN 1-59327-603-6 1. Python (Computer program language) I. Title. QA76.73.P98M38 2015 005.13'3--dc23 2015018135 No Starch Press and the No Starch Press logo are registered trademarks of No Starch Press, Inc. Other product and company names mentioned herein may be the trademarks of their respective owners. Rather than use a trademark symbol with every occurrence of a trademarked name, we are using the names only in an editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the trademark. The information in this book is distributed on an “As Is” basis, without warranty. While every precaution has been taken in the preparation of this work, neither the author nor No Starch Press, Inc. shall have any liability to any person or entity with respect to any loss or damage caused or alleged to be caused directly or indirectly by the information contained in it.

about the author Eric Matthes is a high school science and math teacher living in Alaska, where he teaches an introductory Python course. He has been writing programs since he was five years old. Eric currently focuses on writing soft- ware that addresses inefficiencies in education and brings the benefits of open source software to the field of education. In his spare time he enjoys climbing mountains and spending time with his family. about the technical reviewer Kenneth Love has been a Python programmer and teacher for many years. He has given talks and tutorials at conferences, done professional train- ings, been a Python and Django freelancer, and now teaches for an online education company. Kenneth is also the co-creator of the django-braces package, which provides several handy mixins for Django’s class-based views. You can keep up with him on Twitter at @kennethlove.

For my father, who always made time to answer my questions about programming, and for Ever, who is just beginning to ask me his questions

B r I e f C o n t e n t s Acknowledgments xxvii Introduction xxix Part I: BasICs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Chapter 1: Getting Started 3 Chapter 2: Variables and Simple Data Types 19 Chapter 3: Introducing Lists 37 Chapter 4: Working with Lists 53 Chapter 5: if Statements 75 Chapter 6: Dictionaries 95 Chapter 7: User Input and while Loops 117 Chapter 8: Functions 133 Chapter 9: Classes 161 Chapter 10: Files and Exceptions 189 Chapter 11: Testing Your Code 215 Part II: ProjeCts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231 Project 1: Alien Invasion Chapter 12: A Ship That Fires Bullets 235 Chapter 13: Aliens! 265 Chapter 14: Scoring 291

x Brief Contents Project 2: Data Visualization Chapter 15: Generating Data 321 Chapter 16: Downloading Data 349 Chapter 17: Working with APIs 377 Project 3: Web Applications Chapter 18: Getting Started with Django 397 Chapter 19: User Accounts 427 Chapter 20: Styling and Deploying an App 455 Afterword 483 Appendix A: Installing Python 485 Appendix B: Text Editors 491 Appendix C: Getting Help 499 Appendix D: Using Git for Version Control 505 Index 515

C o n t e n t s I n D e t a I l aCknowledgments xxvii IntroduCtIon xxix Who Is This Book For? xxx What Can You Expect to Learn? xxx Why Python? xxxi Part I: BasICs 1 1 gettIng started 3 Setting Up Your Programming Environment 3 Python 2 and Python 3 4 Running Snippets of Python Code 4 Hello World! 4 Python on Different Operating Systems 5 Python on Linux 5 Python on OS X 8 Python on Windows 10 Troubleshooting Installation Issues 15 Running Python Programs from a Terminal 16 On Linux and OS X 16 On Windows 16 Exercise 1-1: python.org . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Exercise 1-2: Hello World Typos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Exercise 1-3: Infinite Skills . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Summary 17 2 VarIaBles and sImPle data tyPes 19 What Really Happens When You Run hello_world py 19 Variables 20 Naming and Using Variables 21 Avoiding Name Errors When Using Variables 21 Exercise 2-1: Simple Message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 Exercise 2-2: Simple Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 Strings 23 Changing Case in a String with Methods 24 Combining or Concatenating Strings 25 Adding Whitespace to Strings with Tabs or Newlines 26 Stripping Whitespace 26 Avoiding Syntax Errors with Strings 28 Printing in Python 2 29 Exercise 2-3: Personal Message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Exercise 2-4: Name Cases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Exercise 2-5: Famous Quote . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

xii Contents in Detail Exercise 2-6: Famous Quote 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Exercise 2-7: Stripping Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Numbers 30 Integers 30 Floats 30 Avoiding Type Errors with the str() Function 31 Integers in Python 2 32 Exercise 2-8: Number Eight . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 Exercise 2-9: Favorite Number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 Comments 33 How Do You Write Comments? 33 What Kind of Comments Should You Write? 33 Exercise 2-10: Adding Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 The Zen of Python 34 Exercise 2-11: Zen of Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 Summary 36 3 IntroduCIng lIsts 37 What Is a List? 37 Accessing Elements in a List 38 Index Positions Start at 0, Not 1 39 Using Individual Values from a List 39 Exercise 3-1: Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 Exercise 3-2: Greetings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 Exercise 3-3: Your Own List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 Changing, Adding, and Removing Elements 40 Modifying Elements in a List 40 Adding Elements to a List 41 Removing Elements from a List 42 Exercise 3-4: Guest List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Exercise 3-5: Changing Guest List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Exercise 3-6: More Guests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Exercise 3-7: Shrinking Guest List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 Organizing a List 47 Sorting a List Permanently with the sort() Method 47 Sorting a List Temporarily with the sorted() Function 48 Printing a List in Reverse Order 49 Finding the Length of a List 49 Exercise 3-8: Seeing the World. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Exercise 3-9: Dinner Guests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Exercise 3-10: Every Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Avoiding Index Errors When Working with Lists 50 Exercise 3-11: Intentional Error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 Summary 52 4 workIng wIth lIsts 53 Looping Through an Entire List 53 A Closer Look at Looping 54 Doing More Work Within a for Loop 55 Doing Something After a for Loop 56

Contents in Detail xiii Avoiding Indentation Errors 57 Forgetting to Indent 57 Forgetting to Indent Additional Lines 58 Indenting Unnecessarily 59 Indenting Unnecessarily After the Loop 59 Forgetting the Colon 60 Exercise 4-1: Pizzas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Exercise 4-2: Animals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Making Numerical Lists 61 Using the range() Function 61 Using range() to Make a List of Numbers 62 Simple Statistics with a List of Numbers 63 List Comprehensions 63 Exercise 4-3: Counting to Twenty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Exercise 4-4: One Million. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Exercise 4-5: Summing a Million . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Exercise 4-6: Odd Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Exercise 4-7: Threes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Exercise 4-8: Cubes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Exercise 4-9: Cube Comprehension. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Working with Part of a List 65 Slicing a List 65 Looping Through a Slice 66 Copying a List 67 Exercise 4-10: Slices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 Exercise 4-11: My Pizzas, Your Pizzas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 Exercise 4-12: More Loops. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 Tuples 69 Defining a Tuple 69 Looping Through All Values in a Tuple 70 Writing over a Tuple 71 Exercise 4-13: Buffet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 Styling Your Code 72 The Style Guide 72 Indentation 72 Line Length 73 Blank Lines 73 Other Style Guidelines 73 Exercise 4-14: PEP 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Exercise 4-15: Code Review. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 Summary 74 5 If statements 75 A Simple Example 76 Conditional Tests 76 Checking for Equality 76 Ignoring Case When Checking for Equality 77 Checking for Inequality 78 Numerical Comparisons 78 Checking Multiple Conditions 79 Checking Whether a Value Is in a List 80

xiv Contents in Detail Checking Whether a Value Is Not in a List 81 Boolean Expressions 81 Exercise 5-1: Conditional Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 Exercise 5-2: More Conditional Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 if Statements 82 Simple if Statements 82 if-else Statements 83 The if-elif-else Chain 84 Using Multiple elif Blocks 86 Omitting the else Block 86 Testing Multiple Conditions 87 Exercise 5-3: Alien Colors #1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 Exercise 5-4: Alien Colors #2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 Exercise 5-5: Alien Colors #3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 Exercise 5-6: Stages of Life. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 Exercise 5-7: Favorite Fruit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 Using if Statements with Lists 89 Checking for Special Items 90 Checking That a List Is Not Empty 91 Using Multiple Lists 92 Exercise 5-8: Hello Admin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 Exercise 5-9: No Users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 Exercise 5-10: Checking Usernames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 Exercise 5-11: Ordinal Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 Styling Your if Statements 94 Exercise 5-12: Styling if statements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 Exercise 5-13: Your Ideas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 Summary 94 6 dICtIonarIes 95 A Simple Dictionary 96 Working with Dictionaries 96 Accessing Values in a Dictionary 97 Adding New Key-Value Pairs 97 Starting with an Empty Dictionary 98 Modifying Values in a Dictionary 99 Removing Key-Value Pairs 100 A Dictionary of Similar Objects 100 Exercise 6-1: Person . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 Exercise 6-2: Favorite Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 Exercise 6-3: Glossary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 Looping Through a Dictionary 102 Looping Through All Key-Value Pairs 103 Looping Through All the Keys in a Dictionary 104 Looping Through a Dictionary’s Keys in Order 106 Looping Through All Values in a Dictionary 107 Exercise 6-4: Glossary 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 Exercise 6-5: Rivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 Exercise 6-6: Polling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 Nesting 109 A List of Dictionaries 109 A List in a Dictionary 111

Contents in Detail xv A Dictionary in a Dictionary 113 Exercise 6-7: People . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .114 Exercise 6-8: Pets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .115 Exercise 6-9: Favorite Places . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .115 Exercise 6-10: Favorite Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .115 Exercise 6-11: Cities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .115 Exercise 6-12: Extensions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .115 Summary 115 7 user InPut and whIle looPs 117 How the input() Function Works 118 Writing Clear Prompts 118 Using int() to Accept Numerical Input 119 The Modulo Operator 120 Accepting Input in Python 2 7 121 Exercise 7-1: Rental Car. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 Exercise 7-2: Restaurant Seating . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 Exercise 7-3: Multiples of Ten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 Introducing while Loops 122 The while Loop in Action 122 Letting the User Choose When to Quit 122 Using a Flag 124 Using break to Exit a Loop 125 Using continue in a Loop 126 Avoiding Infinite Loops 126 Exercise 7-4: Pizza Toppings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 Exercise 7-5: Movie Tickets. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 Exercise 7-6: Three Exits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 Exercise 7-7: Infinity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 Using a while Loop with Lists and Dictionaries 128 Moving Items from One List to Another 128 Removing All Instances of Specific Values from a List 129 Filling a Dictionary with User Input 130 Exercise 7-8: Deli . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 Exercise 7-9: No Pastrami . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 Exercise 7-10: Dream Vacation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 Summary 131 8 funCtIons 133 Defining a Function 134 Passing Information to a Function 134 Arguments and Parameters 135 Exercise 8-1: Message. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 Exercise 8-2: Favorite Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 Passing Arguments 135 Positional Arguments 136 Keyword Arguments 137 Default Values 138

xvi Contents in Detail Equivalent Function Calls 139 Avoiding Argument Errors 140 Exercise 8-3: T-Shirt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 Exercise 8-4: Large Shirts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 Exercise 8-5: Cities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141 Return Values 141 Returning a Simple Value 142 Making an Argument Optional 142 Returning a Dictionary 144 Using a Function with a while Loop 145 Exercise 8-6: City Names. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 Exercise 8-7: Album. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 Exercise 8-8: User Albums . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 Passing a List 147 Modifying a List in a Function 147 Preventing a Function from Modifying a List 149 Exercise 8-9: Magicians. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 Exercise 8-10: Great Magicians . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 Exercise 8-11: Unchanged Magicians . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 Passing an Arbitrary Number of Arguments 151 Mixing Positional and Arbitrary Arguments 152 Using Arbitrary Keyword Arguments 152 Exercise 8-12: Sandwiches. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 Exercise 8-13: User Profile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 Exercise 8-14: Cars. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 Storing Your Functions in Modules 154 Importing an Entire Module 154 Importing Specific Functions 156 Using as to Give a Function an Alias 156 Using as to Give a Module an Alias 157 Importing All Functions in a Module 157 Styling Functions 158 Exercise 8-15: Printing Models . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 Exercise 8-16: Imports . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 Exercise 8-17: Styling Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 Summary 159 9 Classes 161 Creating and Using a Class 162 Creating the Dog Class 162 Making an Instance from a Class 164 Exercise 9-1: Restaurant. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 Exercise 9-2: Three Restaurants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 Exercise 9-3: Users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166 Working with Classes and Instances 167 The Car Class 167 Setting a Default Value for an Attribute 168 Modifying Attribute Values 168 Exercise 9-4: Number Served . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 Exercise 9-5: Login Attempts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171

Contents in Detail xvii Inheritance 172 The __init__() Method for a Child Class 172 Inheritance in Python 2 7 173 Defining Attributes and Methods for the Child Class 174 Overriding Methods from the Parent Class 175 Instances as Attributes 175 Modeling Real-World Objects 177 Exercise 9-6: Ice Cream Stand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 Exercise 9-7: Admin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 Exercise 9-8: Privileges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 Exercise 9-9: Battery Upgrade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178 Importing Classes 179 Importing a Single Class 179 Storing Multiple Classes in a Module 180 Importing Multiple Classes from a Module 181 Importing an Entire Module 182 Importing All Classes from a Module 182 Importing a Module into a Module 183 Finding Your Own Workflow 184 Exercise 9-10: Imported Restaurant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 Exercise 9-11: Imported Admin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 Exercise 9-12: Multiple Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 The Python Standard Library 184 Exercise 9-13: OrderedDict Rewrite. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 Exercise 9-14: Dice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 Exercise 9-15: Python Module of the Week . . . . . . . . . . . . . . . . . . . . . . . . 186 Styling Classes 186 Summary 187 10 fIles and exCePtIons 189 Reading from a File 190 Reading an Entire File 190 File Paths 191 Reading Line by Line 193 Making a List of Lines from a File 194 Working with a File’s Contents 194 Large Files: One Million Digits 195 Is Your Birthday Contained in Pi? 196 Exercise 10-1: Learning Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 Exercise 10-2: Learning C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 Writing to a File 197 Writing to an Empty File 197 Writing Multiple Lines 198 Appending to a File 199 Exercise 10-3: Guest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 Exercise 10-4: Guest Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 Exercise 10-5: Programming Poll. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 Exceptions 200 Handling the ZeroDivisionError Exception 200 Using try-except Blocks 200 Using Exceptions to Prevent Crashes 201

xviii Contents in Detail The else Block 202 Handling the FileNotFoundError Exception 203 Analyzing Text 204 Working with Multiple Files 205 Failing Silently 206 Deciding Which Errors to Report 207 Exercise 10-6: Addition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207 Exercise 10-7: Addition Calculator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208 Exercise 10-8: Cats and Dogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208 Exercise 10-9: Silent Cats and Dogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208 Exercise 10-10: Common Words . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208 Storing Data 208 Using json dump() and json load() 209 Saving and Reading User-Generated Data 210 Refactoring 212 Exercise 10-11: Favorite Number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214 Exercise 10-12: Favorite Number Remembered . . . . . . . . . . . . . . . . . . . . . 214 Exercise 10-13: Verify User . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214 Summary 214 11 testIng your Code 215 Testing a Function 216 Unit Tests and Test Cases 217 A Passing Test 217 A Failing Test 218 Responding to a Failed Test 219 Adding New Tests 221 Exercise 11-1: City, Country . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 Exercise 11-2: Population. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 Testing a Class 222 A Variety of Assert Methods 222 A Class to Test 223 Testing the AnonymousSurvey Class 225 The setUp() Method 227 Exercise 11-3: Employee . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228 Summary 228 Part II: ProjeCts 231 ProjeCt 1: alIen InVasIon 12 a shIP that fIres Bullets 235 Planning Your Project 236 Installing Pygame 236 Installing Python Packages with pip 237 Installing Pygame on Linux 238

Contents in Detail xix Installing Pygame on OS X 239 Installing Pygame on Windows 240 Starting the Game Project 240 Creating a Pygame Window and Responding to User Input 241 Setting the Background Color 242 Creating a Settings Class 243 Adding the Ship Image 244 Creating the Ship Class 245 Drawing the Ship to the Screen 246 Refactoring: the game_functions Module 247 The check_events() Function 247 The update_screen() Function 248 Exercise 12-1: Blue Sky . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 Exercise 12-2: Game Character . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 Piloting the Ship 249 Responding to a Keypress 249 Allowing Continuous Movement 250 Moving Both Left and Right 252 Adjusting the Ship’s Speed 253 Limiting the Ship’s Range 255 Refactoring check_events() 255 A Quick Recap 256 alien_invasion py 256 settings py 256 game_functions py 256 ship py 257 Exercise 12-3: Rocket . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257 Exercise 12-4: Keys. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257 Shooting Bullets 257 Adding the Bullet Settings 257 Creating the Bullet Class 258 Storing Bullets in a Group 259 Firing Bullets 260 Deleting Old Bullets 261 Limiting the Number of Bullets 262 Creating the update_bullets() Function 263 Creating the fire_bullet() Function 264 Exercise 12-5: Sideways Shooter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 264 Summary 264 13 alIens! 265 Reviewing Your Project 266 Creating the First Alien 266 Creating the Alien Class 267 Creating an Instance of the Alien 268 Making the Alien Appear Onscreen 268 Building the Alien Fleet 269 Determining How Many Aliens Fit in a Row 269 Creating Rows of Aliens 270 Creating the Fleet 271

xx Contents in Detail Refactoring create_fleet() 273 Adding Rows 273 Exercise 13-1: Stars. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276 Exercise 13-2: Better Stars . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276 Making the Fleet Move 276 Moving the Aliens Right 276 Creating Settings for Fleet Direction 277 Checking to See Whether an Alien Has Hit the Edge 278 Dropping the Fleet and Changing Direction 278 Exercise 13-3: Raindrops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279 Exercise 13-4: Steady Rain. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279 Shooting Aliens 280 Detecting Bullet Collisions 280 Making Larger Bullets for Testing 281 Repopulating the Fleet 282 Speeding Up the Bullets 283 Refactoring update_bullets() 283 Exercise 13-5: Catch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284 Ending the Game 284 Detecting Alien-Ship Collisions 284 Responding to Alien-Ship Collisions 285 Aliens that Reach the Bottom of the Screen 288 Game Over! 288 Identifying When Parts of the Game Should Run 289 Exercise 13-6: Game Over. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290 Summary 290 14 sCorIng 291 Adding the Play Button 292 Creating a Button Class 292 Drawing the Button to the Screen 294 Starting the Game 295 Resetting the Game 296 Deactivating the Play Button 297 Hiding the Mouse Cursor 298 Exercise 14-1: Press P to Play . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298 Exercise 14-2: Target Practice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298 Leveling Up 299 Modifying the Speed Settings 299 Resetting the Speed 300 Exercise 14-3: Challenging Target Practice. . . . . . . . . . . . . . . . . . . . . . . . . 301 Scoring 301 Displaying the Score 301 Making a Scoreboard 303 Updating the Score as Aliens Are Shot Down 304 Making Sure to Score All Hits 305 Increasing Point Values 306 Rounding the Score 307 High Scores 308

Contents in Detail xxi Displaying the Level 310 Displaying the Number of Ships 313 Exercise 14-4: All-Time High Score . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317 Exercise 14-5: Refactoring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317 Exercise 14-6: Expanding Alien Invasion . . . . . . . . . . . . . . . . . . . . . . . . . . 317 Summary 317 ProjeCt 2: data VIsualIzatIon 15 generatIng data 321 Installing matplotlib 322 On Linux 322 On OS X 322 On Windows 323 Testing matplotlib 323 The matplotlib Gallery 323 Plotting a Simple Line Graph 324 Changing the Label Type and Graph Thickness 324 Correcting the Plot 326 Plotting and Styling Individual Points with scatter() 326 Plotting a Series of Points with scatter() 328 Calculating Data Automatically 328 Removing Outlines from Data Points 329 Defining Custom Colors 330 Using a Colormap 330 Saving Your Plots Automatically 331 Exercise 15-1: Cubes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331 Exercise 15-2: Colored Cubes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331 Random Walks 331 Creating the RandomWalk() Class 332 Choosing Directions 332 Plotting the Random Walk 333 Generating Multiple Random Walks 334 Styling the Walk 335 Coloring the Points 335 Plotting the Starting and Ending Points 336 Cleaning Up the Axes 337 Adding Plot Points 337 Altering the Size to Fill the Screen 338 Exercise 15-3: Molecular Motion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339 Exercise 15-4: Modified Random Walks . . . . . . . . . . . . . . . . . . . . . . . . . . 339 Exercise 15-5: Refactoring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339 Rolling Dice with Pygal 339 Installing Pygal 340 The Pygal Gallery 340 Creating the Die Class 340 Rolling the Die 341 Analyzing the Results 341

xxii Contents in Detail Making a Histogram 342 Rolling Two Dice 343 Rolling Dice of Different Sizes 345 Exercise 15-6: Automatic Labels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346 Exercise 15-7: Two D8s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346 Exercise 15-8: Three Dice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346 Exercise 15-9: Multiplication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346 Exercise 15-10: Practicing with Both Libraries. . . . . . . . . . . . . . . . . . . . . . . 346 Summary 347 16 downloadIng data 349 The CSV File Format 350 Parsing the CSV File Headers 350 Printing the Headers and Their Positions 351 Extracting and Reading Data 352 Plotting Data in a Temperature Chart 353 The datetime Module 354 Plotting Dates 355 Plotting a Longer Timeframe 356 Plotting a Second Data Series 357 Shading an Area in the Chart 358 Error-Checking 359 Exercise 16-1: San Francisco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362 Exercise 16-2: Sitka-Death Valley Comparison . . . . . . . . . . . . . . . . . . . . . . 362 Exercise 16-3: Rainfall . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362 Exercise 16-4: Explore. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362 Mapping Global Data Sets: JSON Format 362 Downloading World Population Data 362 Extracting Relevant Data 363 Converting Strings into Numerical Values 364 Obtaining Two-Digit Country Codes 365 Building a World Map 367 Plotting Numerical Data on a World Map 368 Plotting a Complete Population Map 369 Grouping Countries by Population 371 Styling World Maps in Pygal 372 Lightening the Color Theme 374 Exercise 16-5: All Countries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375 Exercise 16-6: Gross Domestic Product . . . . . . . . . . . . . . . . . . . . . . . . . . . 375 Exercise 16-7: Choose Your Own Data . . . . . . . . . . . . . . . . . . . . . . . . . . . 375 Exercise 16-8: Testing the country_codes Module . . . . . . . . . . . . . . . . . . . . 375 Summary 375 17 workIng wIth aPIs 377 Using a Web API 378 Git and GitHub 378 Requesting Data Using an API Call 378 Installing Requests 379

Contents in Detail xxiii Processing an API Response 379 Working with the Response Dictionary 380 Summarizing the Top Repositories 382 Monitoring API Rate Limits 383 Visualizing Repositories Using Pygal 384 Refining Pygal Charts 386 Adding Custom Tooltips 387 Plotting the Data 388 Adding Clickable Links to Our Graph 390 The Hacker News API 390 Exercise 17-1: Other Languages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393 Exercise 17-2: Active Discussions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393 Exercise 17-3: Testing python_repos.py . . . . . . . . . . . . . . . . . . . . . . . . . . . 393 Summary 393 ProjeCt 3: weB aPPlICatIons 18 gettIng started wIth django 397 Setting Up a Project 398 Writing a Spec 398 Creating a Virtual Environment 398 Installing virtualenv 399 Activating the Virtual Environment 399 Installing Django 400 Creating a Project in Django 400 Creating the Database 401 Viewing the Project 401 Exercise 18-1: New Projects. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402 Starting an App 403 Defining Models 403 Activating Models 404 The Django Admin Site 406 Defining the Entry Model 408 Migrating the Entry Model 409 Registering Entry with the Admin Site 409 The Django Shell 410 Exercise 18-2: Short Entries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412 Exercise 18-3: The Django API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412 Exercise 18-4: Pizzeria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412 Making Pages: The Learning Log Home Page 412 Mapping a URL 413 Writing a View 414 Writing a Template 415 Exercise 18-5: Meal Planner. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416 Exercise 18-6: Pizzeria Home Page. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 416 Building Additional Pages 416 Template Inheritance 416 The Topics Page 418 Individual Topic Pages 421

xxiv Contents in Detail Exercise 18-7: Template Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . 424 Exercise 18-8: Pizzeria Pages. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 424 Summary 425 19 user aCCounts 427 Allowing Users to Enter Data 428 Adding New Topics 428 Adding New Entries 432 Editing Entries 435 Exercise 19-1: Blog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 438 Setting Up User Accounts 439 The users App 439 The Login Page 440 Logging Out 442 The Registration Page 443 Exercise 19-2: Blog Accounts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446 Allowing Users to Own Their Data 446 Restricting Access with @login_required 447 Connecting Data to Certain Users 448 Restricting Topics Access to Appropriate Users 451 Protecting a User’s Topics 451 Protecting the edit_entry Page 452 Associating New Topics with the Current User 453 Exercise 19-3: Refactoring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454 Exercise 19-4: Protecting new_entry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454 Exercise 19-5: Protected Blog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454 Summary 454 20 stylIng and dePloyIng an aPP 455 Styling Learning Log 456 The django-bootstrap3 App 456 Using Bootstrap to Style Learning Log 457 Modifying base html 458 Styling the Home Page Using a Jumbotron 461 Styling the Login Page 461 Styling the new_topic Page 463 Styling the Topics Page 463 Styling the Entries on the Topic Page 464 Exercise 20-1: Other Forms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 466 Exercise 20-2: Stylish Blog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 466 Deploying Learning Log 466 Making a Heroku Account 466 Installing the Heroku Toolbelt 466 Installing Required Packages 466 Creating a Packages List with a requirements txt File 467 Specifying the Python Runtime 468 Modifying settings py for Heroku 468 Making a Procfile to Start Processes 469 Modifying wsgi py for Heroku 470

Contents in Detail xxv Making a Directory for Static Files 470 Using the gunicorn Server Locally 470 Using Git to Track the Project’s Files 471 Pushing to Heroku 473 Setting Up the Database on Heroku 474 Refining the Heroku Deployment 475 Securing the Live Project 476 Committing and Pushing Changes 477 Creating Custom Error Pages 478 Ongoing Development 480 The SECRET_KEY Setting 481 Deleting a Project on Heroku 481 Exercise 20-3: Live Blog. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 482 Exercise 20-4: More 404s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 482 Exercise 20-5: Extended Learning Log . . . . . . . . . . . . . . . . . . . . . . . . . . . . 482 Summary 482 afterword 483 a InstallIng Python 485 Python on Linux 485 Finding the Installed Version 486 Installing Python 3 on Linux 486 Python on OS X 486 Finding the Installed Version 486 Using Homebrew to Install Python 3 487 Python on Windows 488 Installing Python 3 on Windows 488 Finding the Python Interpreter 488 Adding Python to Your Path Variable 489 Python Keywords and Built-in Functions 489 Python Keywords 489 Python Built-in Functions 490 B text edItors 491 Geany 492 Installing Geany on Linux 492 Installing Geany on Windows 492 Running Python Programs in Geany 493 Customizing Geany Settings 493 Sublime Text 494 Installing Sublime Text on OS X 494 Installing Sublime Text on Linux 494 Installing Sublime Text on Windows 495 Running Python Programs in Sublime Text 495 Configuring Sublime Text 495 Customizing Sublime Text Settings 496

xxvi Contents in Detail IDLE 496 Installing IDLE on Linux 496 Installing IDLE on OS X 496 Installing IDLE on Windows 497 Customizing IDLE Settings 497 Emacs and vim 497 C gettIng helP 499 First Steps 499 Try It Again 500 Take a Break 500 Refer to This Book’s Resources 500 Searching Online 501 Stack Overflow 501 The Official Python Documentation 501 Official Library Documentation 502 r/learnpython 502 Blog Posts 502 IRC (Internet Relay Chat) 502 Make an IRC Account 502 Channels to Join 503 IRC Culture 503 d usIng gIt for VersIon Control 505 Installing Git 506 Installing Git on Linux 506 Installing Git on OS X 506 Installing Git on Windows 506 Configuring Git 506 Making a Project 507 Ignoring Files 507 Initializing a Repository 507 Checking the Status 508 Adding Files to the Repository 508 Making a Commit 509 Checking the Log 509 The Second Commit 510 Reverting a Change 511 Checking Out Previous Commits 512 Deleting the Repository 513 Index 515

a C k n o w l e D g m e n t s This book would not have been possible without the wonderful and extremely professional staff at No Starch Press. Bill Pollock invited me to write an introductory book, and I deeply appreciate that original offer. Tyler Ortman helped shape my thinking in the early stages of drafting. Liz Chadwick’s and Leslie Shen’s initial feedback on each chapter was invaluable, and Anne Marie Walker helped to clarify many parts of the book. Riley Hoffman answered every question I had about the process of assembling a complete book and patiently turned my work into a beautiful finished product. I’d like to thank Kenneth Love, the technical reviewer for Python Crash Course. I met Kenneth at PyCon one year, and his enthusiasm for the lan- guage and the Python community has been a constant source of profes- sional inspiration ever since. Kenneth went beyond simple fact-checking and reviewed the book with the goal of helping beginning programmers develop a solid understanding of the Python language and programming in general. That said, any inaccuracies that remain are completely my own. I’d like to thank my father for introducing me to programming at a young age and for not being afraid that I’d break his equipment. I’d like to thank my wife, Erin, for supporting and encouraging me through the writing of this book, and I’d like to thank my son, Ever, whose curiosity inspires me every single day.

I n t r o D u C t I o n Every programmer has a story about how they learned to write their first pro- gram. I started learning as a child when my father was working for Digital Equipment Corporation, one of the pioneering companies of the modern computing era. I wrote my first program on a kit computer my dad had assembled in our basement. The computer con- sisted of nothing more than a bare motherboard connected to a keyboard without a case, and it had a bare cathode ray tube for a monitor. My initial program was a simple number guessing game, which looked something like this: I'm thinking of a number! Try to guess the number I'm thinking of: 25 Too low! Guess again: 50 Too high! Guess again: 42 That's it! Would you like to play again? (yes/no) no Thanks for playing!

xxx Introduction I’ll always remember how satisfied I felt watching my family play a game that I created and that worked as I intended it to. That early experience had a lasting impact. There is real satisfaction in building something with a purpose, something that solves a problem. The software I write now meets a more significant need than my childhood efforts, but the sense of satisfaction I get from creating a program that works is still largely the same. who Is this Book for? The goal of this book is to bring you up to speed with Python as quickly as possible so you can build programs that work—games, data visualizations, and web applications—while developing a foundation in programming that will serve you well for the rest of your life. Python Crash Course is written for people of any age who have never programmed in Python before or have never programmed at all. If you want to learn the basics of programming quickly so you can focus on interesting projects, and you like to test your understanding of new concepts by solving meaningful problems, this book is for you. Python Crash Course is also perfect for middle school and high school teachers who want to offer their students a project-based introduc- tion to programming. what Can you expect to learn? The purpose of this book is to make you a good programmer in general and a good Python programmer in particular. You’ll learn efficiently and adopt good habits as I provide you with a solid foundation in general pro- gramming concepts. After working your way through Python Crash Course, you should be ready to move on to more advanced Python techniques, and your next programming language will be even easier to grasp. In the first part of this book you’ll learn basic programming concepts you need to know to write Python programs. These concepts are the same as those you’d learn when starting out in almost any programming lan- guage. You’ll learn about different kinds of data and the ways you can store data in lists and dictionaries within your programs. You’ll learn to build collections of data and work through those collections in efficient ways. You’ll learn to use while and if loops to test for certain conditions so you can run specific sections of code while those conditions are true and run other sections when they’re not—a technique that greatly helps to automate processes. You’ll learn to accept input from users to make your programs inter- active and to keep your programs running as long as the user is active. You’ll explore how to write functions to make parts of your program reusable, so you only have to write blocks of code that perform certain

Introduction xxxi actions once, which you can then use as many times as you like. You’ll then extend this concept to more complicated behavior with classes, making fairly simple programs respond to a variety of situations. You’ll learn to write pro- grams that handle common errors gracefully. After working through each of these basic concepts, you’ll write a few short programs that solve some well-defined problems. Finally, you’ll take your first step toward intermedi- ate programming by learning how to write tests for your code so you can develop your programs further without worrying about introducing bugs. All the information in Part I will prepare you for taking on larger, more complex projects. In Part II you’ll apply what you learned in Part I to three projects. You can do any or all of these projects in whichever order works best for you. In the first project (Chapters 12–14) you’ll create a Space Invaders–style shoot- ing game called Alien Invasion, which consists of levels of increasing diffi- culty. After you’ve completed this project, you should be well on your way to being able to develop your own 2D games. The second project (Chapters 15–17) introduces you to data visualiza- tion. Data scientists aim to make sense of the vast amount of information available to them through a variety of visualization techniques. You’ll work with data sets that you generate through code, data sets downloaded from online sources, and data sets your programs download automatically. After you’ve completed this project, you’ll be able to write programs that sift through large data sets and make visual representations of that stored information. In the third project (Chapters 18–20) you’ll build a small web applica- tion called Learning Log. This project allows you to keep a journal of ideas and concepts you’ve learned about a specific topic. You’ll be able to keep separate logs for different topics and allow others to create an account and start their own journals. You’ll also learn how to deploy your project so any- one can access it online from anywhere. why Python? Every year I consider whether to continue using Python or whether to move on to a different language—perhaps one that’s newer to the programming world. But I continue to focus on Python for many reasons. Python is an incredibly efficient language: your programs will do more in fewer lines of code than many other languages would require. Python’s syntax will also help you write “clean” code. Your code will be easy to read, easy to debug, and easy to extend and build upon compared to other languages. People use Python for many purposes: to make games, build web appli- cations, solve business problems, and develop internal tools at all kinds of interesting companies. Python is also used heavily in scientific fields for academic research and applied work.

xxxii Introduction One of the most important reasons I continue to use Python is because of the Python community, which includes an incredibly diverse and welcoming group of people. Community is essential to program- mers because programming isn’t a solitary pursuit. Most of us, even the most experienced programmers, need to ask advice from others who have already solved similar problems. Having a well-connected and supportive community is critical in helping you solve problems, and the Python com- munity is fully supportive of people like you who are learning Python as your first programming language. Python is a great language to learn, so let’s get started!

Part I B a s I C s Part I of this book teaches you the basic concepts you’ll need to write Python programs. Many of these concepts are common to all programming languages, so they’ll be useful throughout your life as a programmer. In Chapter 1 you’ll install Python on your computer and run your first program, which prints the message Hello world! to the screen. In Chapter 2 you’ll learn to store information in variables and work with text and numerical values. Chapters 3 and 4 introduce lists. Lists can store as much information as you want in one variable, allowing you to work with that data efficiently. You’ll be able to work with hundreds, thousands, and even millions of values in just a few lines of code. In Chapter 5 you’ll use if statements to write code that responds one way if certain conditions are true, and responds in a different way if those conditions are not true. Chapter 6 shows you how to use Python’s dictionaries, which let you make connections between different pieces of information. Like lists, dic- tionaries can contain as much information as you need to store. In Chapter 7 you’ll learn how to accept input from users to make your programs interactive. You’ll also learn about while loops, which run blocks of code repeatedly as long as certain conditions remain true. In Chapter 8 you’ll write functions, which are named blocks of code that perform a specific task and can be run whenever you need them.

2 Part I Chapter 9 introduces classes, which allow you to model real-world objects, such as dogs, cats, people, cars, rockets, and much more, so your code can represent anything real or abstract. Chapter 10 shows you how to work with files and handle errors so your programs won’t crash unexpectedly. You’ll store data before your program closes, and read the data back in when the program runs again. You’ll learn about Python’s exceptions, which allow you to anticipate errors, and make your programs handle those errors gracefully. In Chapter 11 you’ll learn to write tests for your code to check that your programs work the way you intend them to. As a result, you’ll be able to expand your programs without worrying about introducing new bugs. Testing your code is one of the first skills that will help you transition from beginner to intermediate programmer.

1g e t t I n g s t a r t e D In this chapter you’ll run your first Python program, hello_world.py. First, you’ll need to check whether Python is installed on your computer; if it isn’t, you’ll install it. You’ll also install a text editor to work with your Python programs. Text editors recognize Python code and highlight sections as you write, making it easy to understand the structure of your code. setting up your Programming environment Python differs slightly on different operating systems, so you’ll need to keep a few considerations in mind. Here, we’ll look at the two major versions of Python currently in use and outline the steps to set up Python on your system.

4 Chapter 1 Python 2 and Python 3 Today, two versions of Python are available: Python 2 and the newer Python 3. Every programming language evolves as new ideas and tech- nologies emerge, and the developers of Python have continually made the language more versatile and powerful. Most changes are incremental and hardly noticeable, but in some cases code written for Python 2 may not run properly on systems with Python 3 installed. Throughout this book I’ll point out areas of significant difference between Python 2 and Python 3, so whichever version you use, you’ll be able to follow the instructions. If both versions are installed on your system or if you need to install Python, use Python 3. If Python 2 is the only version on your system and you’d rather jump into writing code instead of installing Python, you can start with Python 2. But the sooner you upgrade to using Python 3 the better, so you’ll be working with the most recent version. Running Snippets of Python Code Python comes with an interpreter that runs in a terminal window, allow- ing you to try bits of Python without having to save and run an entire program. Throughout this book, you’ll see snippets that look like this: u >>> print("Hello Python interpreter!") Hello Python interpreter! The text in bold is what you’ll type in and then execute by pressing enter. Most of the examples in the book are small, self-contained programs that you’ll run from your editor, because that’s how you’ll write most of your code. But sometimes basic concepts will be shown in a series of snippets run through a Python terminal session to demonstrate isolated concepts more efficiently. Any time you see the three angle brackets in a code listing u, you’re looking at the output of a terminal session. We’ll try coding in the interpreter for your system in a moment. Hello World! A long-held belief in the programming world has been that printing a Hello world! message to the screen as your first program in a new language will bring you luck. In Python, you can write the Hello World program in one line: print("Hello world!") Such a simple program serves a very real purpose. If it runs correctly on your system, any Python program you write should work as well. We’ll look at writing this program on your particular system in just a moment.

Getting Started 5 Python on different operating systems Python is a cross-platform programming language, which means it runs on all the major operating systems. Any Python program you write should run on any modern computer that has Python installed. However, the methods for setting up Python on different operating systems vary slightly. In this section you’ll learn how to set up Python and run the Hello World program on your own system. You’ll first check whether Python is installed on your system and install it if it’s not. Then you’ll install a simple text edi- tor and save an empty Python file called hello_world.py. Finally, you’ll run the Hello World program and troubleshoot anything that didn’t work. I’ll walk you through this process for each operating system, so you’ll have a beginner-friendly Python programming environment. Python on Linux Linux systems are designed for programming, so Python is already installed on most Linux computers. The people who write and maintain Linux expect you to do your own programming at some point and encourage you to do so. For this reason there’s very little you have to install and very few settings you have to change to start programming. Checking Your Version of Python Open a terminal window by running the Terminal application on your system (in Ubuntu, you can press ctrl-alt-T). To find out whether Python is installed, enter python with a lowercase p. You should see output telling you which version of Python is installed and a >>> prompt where you can start entering Python commands, like this: $ python Python 2.7.6 (default, Mar 22 2014, 22:59:38) [GCC 4.8.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> This output tells you that Python 2.7.6 is currently the default version of Python installed on this computer. When you’ve seen this output, press ctrl-D or enter exit() to leave the Python prompt and return to a terminal prompt. To check for Python 3, you might have to specify that version; so even if the output displayed Python 2.7 as the default version, try the command python3: $ python3 Python 3.5.0 (default, Sep 17 2015, 13:05:18) [GCC 4.8.4] on linux Type "help", "copyright", "credits" or "license" for more information. >>>

6 Chapter 1 This output means you also have Python 3 installed, so you’ll be able to use either version. Whenever you see the python command in this book, enter python3 instead. Most Linux distributions have Python already installed, but if for some reason yours didn’t or if your system came with Python 2 and you want to install Python 3, refer to Appendix A. Installing a text Editor Geany is a simple text editor: it’s easy to install, will let you run almost all your programs directly from the editor instead of through a terminal, uses syntax highlighting to color your code, and runs your code in a terminal window so you’ll get used to using terminals. Appendix B provides informa- tion on other text editors, but I recommend using Geany unless you have a good reason to use a different editor. You can install Geany in one line on most Linux systems: $ sudo apt-get install geany If this doesn’t work, see the instructions at http://geany.org/Download/ ThirdPartyPackages/. running the Hello World Program To start your first program, open Geany. Press the Super key (often called the Windows key) and search for Geany on your system. Make a shortcut by dragging the icon to your taskbar or desktop. Then make a folder some- where on your system for your projects and call it python_work. (It’s best to use lowercase letters and underscores for spaces in file and folder names because these are Python naming conventions.) Go back to Geany and save an empty Python file (File4Save As) called hello_world.py in your python_ work folder. The extension .py tells Geany your file will contain a Python program. It also tells Geany how to run your program and highlight the text in a helpful way. After you’ve saved your file, enter the following line: print("Hello Python world!") If multiple versions of Python are installed on your system, you need to make sure Geany is configured to use the correct version. Go to Build4Set Build Commands. You should see the words Compile and Execute with a com- mand next to each. Geany assumes the correct command for each is python, but if your system uses the python3 command, you’ll need to change this. If the command python3 worked in a terminal session, change the Compile and Execute commands so Geany will use the Python 3 inter- preter. Your Compile command should look like this: python3 -m py_compile "%f"

Getting Started 7 You need to type this command exactly as it’s shown. Make sure the spaces and capitalization match what is shown here. Your Execute command should look like this: python3 "%f" Again, make sure the spacing and capitalization match what is shown here. Figure 1-1 shows how these commands should look in Geany’s con- figuration menu. Figure 1-1: Here, Geany is configured to use Python 3 on Linux. Now run hello_world.py by selecting Build4Execute in the menu, by clicking the Execute icon (which shows a set of gears), or by pressing F5. A terminal window should pop up with the following output: Hello Python world! ------------------ (program exited with code: 0) Press return to continue If you don’t see this, check every character on the line you entered. Did you accidentally capitalize print? Did you forget one or both of the quota- tion marks or parentheses? Programming languages expect very specific syntax, and if you don’t provide that, you’ll get errors. If you can’t get the program to run, see “Troubleshooting Installation Issues” on page 15.

8 Chapter 1 running Python in a terminal Session You can try running snippets of Python code by opening a terminal and typing python or python3, as you did when checking your version. Do this again, but this time enter the following line in the terminal session: >>> print("Hello Python interpreter!") Hello Python interpreter! >>> You should see your message printed directly in the current terminal window. Remember that you can close the Python interpreter by pressing ctrl-D or by typing the command exit(). Python on OS X Python is already installed on most OS X systems. Once you know Python is installed, you’ll need to install a text editor and make sure it’s configured correctly. Checking Whether Python Is Installed Open a terminal window by going to Applications4Utilities4Terminal. You can also press command-spacebar, type terminal, and then press enter. To find out whether Python is installed, enter python with a lowercase p. You should see output telling you which version of Python is installed on your system and a >>> prompt where you can start entering Python commands, like this: $ python Python 2.7.5 (default, Mar 9 2014, 22:15:05) [GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin Type "help", "copyright", "credits", or "license" for more information. >>> This output tells you that Python 2.7.5 is currently the default version installed on this computer. When you’ve seen this output, press ctrl-D or enter exit() to leave the Python prompt and return to a terminal prompt. To check for Python 3, try the command python3. You might get an error message, but if the output shows you have Python 3 installed, you’ll be able to use Python 3 without having to install it. If python3 works on your system, whenever you see the python command in this book, make sure you use python3 instead. If for some reason your system didn’t come with Python or if you only have Python 2 and you want to install Python 3 now, see Appendix A.

Getting Started 9 running Python in a terminal Session You can try running snippets of Python code by opening a terminal and typing python or python3, as you did when checking your version. Do this again, but this time enter the following line in the terminal session: >>> print("Hello Python interpreter!") Hello Python interpreter! >>> You should see your message printed directly in the current terminal window. Remember that you can close the Python interpreter by pressing ctrl-D or by typing the command exit(). Installing a text Editor Sublime Text is a simple text editor: it’s easy to install on OS X, will let you run almost all of your programs directly from the editor instead of through a terminal, uses syntax highlighting to color your code, and runs your code in a terminal session embedded in the Sublime Text window to make it easy to see the output. Appendix B provides information on other text editors, but I recommend using Sublime Text unless you have a good reason to use a different editor. You can download an installer for Sublime Text from http://sublimetext .com/3. Click the download link and look for an installer for OS X. Sublime Text has a very liberal licensing policy: you can use the editor for free as long as you want, but the author requests that you purchase a license if you like it and want continual use. After the installer has been downloaded, open it and then drag the Sublime Text icon into your Applications folder. Configuring Sublime text for Python 3 If you use a command other than python to start a Python terminal session, you’ll need to configure Sublime Text so it knows where to find the correct version of Python on your system. Issue the following command to find out the full path to your Python interpreter: $ type -a python3 python3 is /usr/local/bin/python3 Now open Sublime Text, and go to Tools4Build System4New Build System, which will open a new configuration file for you. Delete what you see and enter the following: Python3 { .sublime-build "cmd": ["/usr/local/bin/python3", "-u", "$file"], }

10 Chapter 1 This code tells Sublime Text to use your system’s python3 command when running the currently open file. Make sure you use the path you found when issuing the command type -a python3 in the previous step. Save the file as Python3.sublime-build in the default directory that Sublime Text opens when you choose Save. running the Hello World Program To start your first program, launch Sublime Text by opening the Applications folder and double-clicking the Sublime Text icon. You can also press command-spacebar and enter sublime text in the search bar that pops up. Make a folder called python_work somewhere on your system for your projects. (It’s best to use lowercase letters and underscores for spaces in file and folder names, because these are Python naming conventions.) Save an empty Python file (File4Save As) called hello_world.py in your python_work folder. The extension .py tells Sublime Text that your file will contain a Python program and tells it how to run your program and highlight the text in a helpful way. After you’ve saved your file, enter the following line: print("Hello Python world!") If the command python works on your system, you can run your pro- gram by selecting Tools4Build in the menu or by pressing ctrl-B. If you configured Sublime Text to use a command other than python, select Tools4Build System and then select Python 3. This sets Python 3 as the default version of Python, and you’ll be able to select Tools4Build or just press command-B to run your programs from now on. A terminal screen should appear at the bottom of the Sublime Text win- dow, showing the following output: Hello Python world! [Finished in 0.1s] If you don’t see this, check every character on the line you entered. Did you accidentally capitalize print? Did you forget one or both of the quota- tion marks or parentheses? Programming languages expect very specific syntax, and if you don’t provide that, you’ll get errors. If you can’t get the program to run, see “Troubleshooting Installation Issues” on page 15. Python on Windows Windows doesn’t always come with Python, so you’ll probably need to down- load and install it, and then download and install a text editor.

Getting Started 11 Installing Python First, check whether Python is installed on your system. Open a command window by entering command into the Start menu or by holding down the shift key while right-clicking on your desktop and selecting Open com- mand window here. In the terminal window, enter python in lowercase. If you get a Python prompt (>>>), Python is installed on your system. However, you’ll probably see an error message telling you that python is not a recog- nized command. In that case, download a Python installer for Windows. Go to http:// python.org/downloads/. You should see two buttons, one for downloading Python 3 and one for downloading Python 2. Click the Python 3 button, which should automatically start downloading the correct installer for your system. After you’ve downloaded the file, run the installer. Make sure you check the option Add Python to PATH, which will make it easier to config- ure your system correctly. Figure 1-2 shows this option checked. Figure 1-2: Make sure you check the box labeled Add Python to PATH. Starting a Python terminal Session Setting up your text editor will be straightforward if you first set up your system to run Python in a terminal session. Open a command window and enter python in lowercase. If you get a Python prompt (>>>), Windows has found the version of Python you just installed: C:\> python Python 3.5.0 (v3.5.0:374f501f4567, Sep 13 2015, 22:15:05) [MSC v.1900 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>>

12 Chapter 1 If this worked, you can move on to the next section, “Running Python in a Terminal Session.” However, you may see output that looks more like this: C:\> python 'python' is not recognized as an internal or external command, operable program or batch file. In this case you need to tell Windows how to find the Python version you just installed. Your system’s python command is usually saved in your C drive, so open Windows Explorer and open your C drive. Look for a folder starting with the name Python, open that folder, and find the python file (in lowercase). For example, I have a Python35 folder with a file named python inside it, so the path to the python command on my system is C:\Python35\ python. Otherwise, enter python into the search box in Windows Explorer to show you exactly where the python command is stored on your system. When you think you know the path, test it by entering that path into a terminal window. Open a command window and enter the full path you just found: C:\> C:\Python35\python Python 3.5.0 (v3.5.0:374f501f4567, Sep 13 2015, 22:15:05) [MSC v.1900 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> If this worked, you know how to access Python on your system. running Python in a terminal Session Enter the following line in your Python session, and make sure you see the output Hello Python world! >>> print("Hello Python world!") Hello Python world! >>> Any time you want to run a snippet of Python code, open a command window and start a Python terminal session. To close the terminal session, press ctrl-Z and then press enter, or enter the command exit(). Installing a text Editor Geany is a simple text editor: it’s easy to install, will let you run almost all of your programs directly from the editor instead of through a terminal, uses syntax highlighting to color your code, and runs your code in a terminal window so you’ll get used to using terminals. Appendix B provides informa- tion on other text editors, but I recommend using Geany unless you have a good reason to use a different editor.

Getting Started 13 You can download a Windows installer for Geany from http://geany.org/. Click Releases under the Download menu, and look for the geany-1.25_ setup.exe installer or something similar. Run the installer and accept all the defaults. To start your first program, open Geany: press the Windows key and search for Geany on your system. You should make a shortcut by dragging the icon to your taskbar or desktop. Make a folder called python_work some- where on your system for your projects. (It’s best to use lowercase letters and underscores for spaces in file and folder names, because these are Python naming conventions.) Go back to Geany and save an empty Python file (File4Save As) called hello_world.py in your python_work folder. The exten- sion .py tells Geany that your file will contain a Python program. It also tells Geany how to run your program and to highlight the text in a helpful way. After you’ve saved your file, type the following line: print("Hello Python world!") If the command python worked on your system, you won’t have to config- ure Geany; skip the next section and move on to “Running the Hello World Program” on page 14. If you needed to enter a path like C:\Python35\python to start a Python interpreter, follow the directions in the next section to configure Geany for your system. Configuring Geany To configure Geany, go to Build4Set Build Commands. You should see the words Compile and Execute with a command next to each. The Compile and Execute commands start with python in lowercase, but Geany doesn’t know where your system stored the python command. You need to add the path you used in the terminal session. In the Compile and Execute commands, add the drive your python command is on and the folder where the python command is stored. Your Compile command should look something like this: C:\Python35\python -m py_compile "%f" Your path might be a little different, but make sure the spaces and capitalization match what is shown here. Your Execute command should look something like this: C:\Python35\python "%f" Again, make sure the spacing and capitalization in your Execute com- mand matches what is shown here. Figure 1-3 shows how these commands should look in Geany’s configuration menu.

14 Chapter 1 Figure 1-3: Here, Geany is configured to use Python 3 on Windows. After you’ve set these commands correctly, click OK. running the Hello World Program You should now be able to run your program successfully. Run hello_world.py by selecting Build4Execute in the menu, by clicking the Execute icon (which shows a set of gears), or by pressing F5. A terminal window should pop up with the following output: Hello Python world! ------------------ (program exited with code: 0) Press return to continue If you don’t see this, check every character on the line you entered. Did you accidentally capitalize print? Did you forget one or both of the quota- tion marks or parentheses? Programming languages expect very specific syntax, and if you don’t provide that, you’ll get errors. If you can’t get the program to run, see the next section for help.

Getting Started 15 troubleshooting Installation Issues Hopefully, setting up your programming environment was successful, but if you’ve been unable to run hello_world.py, here are a few remedies you can try: • When a program contains a significant error, Python displays a trace- back. Python looks through the file and tries to report the problem. The traceback might give you a clue as to what issue is preventing the pro- gram from running. • Step away from your computer, take a short break, and then try again. Remember that syntax is very important in programming, so even a missing colon, a mismatched quotation mark, or mismatched paren- theses can prevent a program from running properly. Reread the rel- evant parts of this chapter, look over what you’ve done, and see if you can find the mistake. • Start over again. You probably don’t need to uninstall anything, but it might make sense to delete your hello_world.py file and create it again from scratch. • Ask someone else to follow the steps in this chapter, on your computer or a different one, and watch what they do carefully. You might have missed one small step that someone else happens to catch. • Find someone who knows Python and ask them to help you get set up. If you ask around, you might find that you know someone who uses Python. • The setup instructions in this chapter are also available online, through https://www.nostarch.com/pythoncrashcourse/. The online version of these instructions may work better for you. • Ask for help online. Appendix C provides a number of resources and areas online, like forums and live chat sites, where you can ask for solu- tions from people who’ve already worked through the issue you’re cur- rently facing. Don’t worry about bothering experienced programmers. Every programmer has been stuck at some point, and most programmers are happy to help you set up your system correctly. As long as you can state clearly what you’re trying to do, what you’ve already tried, and the results you’re getting, there’s a good chance someone will be able to help you. As mentioned in the Introduction, the Python community is very beginner friendly. Python should run well on any modern computer, so find a way to ask for help if you’re having trouble so far. Early issues can be frustrating, but they’re well worth sorting out. Once you get hello_world.py running, you can start to learn Python, and your programming work will become more inter- esting and satisfying.

16 Chapter 1 running Python Programs from a terminal Most of the programs you write in your text editor you’ll run directly from the editor, but sometimes it’s useful to run programs from a terminal instead. For example, you might want to run an existing program without opening it for editing. You can do this on any system with Python installed if you know how to access the directory where you’ve stored your program file. To try this, make sure you’ve saved the hello_world.py file in the python_work folder on your desktop. On Linux and OS X Running a Python program from a terminal session is the same on Linux and OS X. The terminal command cd, for change directory, is used to navi- gate through your file system in a terminal session. The command ls, for list, shows you all the nonhidden files that exist in the current directory. Open a new terminal window and issue the following commands to run hello_world.py: u ~$ cd Desktop/python_work/ v ~/Desktop/python_work$ ls hello_world.py w ~/Desktop/python_work$ python hello_world.py Hello Python world! At u we use the cd command to navigate to the python_work folder, which is in the Desktop folder. Next, we use the ls command to make sure hello_world.py is in this folder v. Then, we run the file using the command python hello_world.py w. It’s that simple. You just use the python (or python3) command to run Python programs. On Windows The terminal command cd, for change directory, is used to navigate through your file system in a command window. The command dir, for directory, shows you all the files that exist in the current directory. Open a new terminal window and issue the following commands to run hello_world.py: u C:\> cd Desktop\python_work v C:\Desktop\python_work> dir hello_world.py w C:\Desktop\python_work> python hello_world.py Hello Python world! At u we use the cd command to navigate to the python_work folder, which is in the Desktop folder. Next, we use the dir command to make sure hello_world.py is in this folder v. Then, we run the file using the command python hello_world.py w.

Getting Started 17 If you haven’t configured your system to use the simple command python, you may need to use the longer version of this command: C:\$ cd Desktop\python_work C:\Desktop\python_work$ dir hello_world.py C:\Desktop\python_work$ C:\Python35\python hello_world.py Hello Python world! Most of your programs will run fine directly from your editor, but as your work becomes more complex, you might write programs that you’ll need to run from a terminal. try It yourse lf The exercises in this chapter are exploratory in nature Starting in Chapter 2, the challenges you’ll solve will be based on what you’ve learned 1-1. python.org: Explore the Python home page (http://python.org/) to find topics that interest you As you become familiar with Python, different parts of the site will be more useful to you 1-2. Hello World Typos: Open the hello_world.py file you just created Make a typo somewhere in the line and run the program again Can you make a typo that generates an error? Can you make sense of the error message? Can you make a typo that doesn’t generate an error? Why do you think it didn’t make an error? 1-3. Infinite Skills: If you had infinite programming skills, what would you build? You’re about to learn how to program If you have an end goal in mind, you’ll have an immediate use for your new skills; now is a great time to draft descrip- tions of what you’d like to create It’s a good habit to keep an “ideas” notebook that you can refer to whenever you want to start a new project Take a few minutes now to describe three programs you’d like to create summary In this chapter you learned a bit about Python in general, and you installed Python to your system if it wasn’t already there. You also installed a text edi- tor to make it easier to write Python code. You learned to run snippets of Python code in a terminal session, and you ran your first actual program, hello_world.py. You probably learned a bit about troubleshooting as well. In the next chapter you’ll learn about the different kinds of data you can work with in your Python programs, and you’ll learn to use variables as well.

2V a r I a B l e s a n D s I m P l e D a t a t y P e s In this chapter you’ll learn about the dif- ferent kinds of data you can work with in your Python programs. You’ll also learn how to store your data in variables and how to use those variables in your programs. what really happens when you run hello_world.py Let’s take a closer look at what Python does when you run hello_world.py. As it turns out, Python does a fair amount of work, even when it runs a simple program: hello_world.py print("Hello Python world!")

20 Chapter 2 When you run this code, you should see this output: Hello Python world! When you run the file hello_world.py, the ending .py indicates that the file is a Python program. Your editor then runs the file through the Python interpreter, which reads through the program and determines what each word in the program means. For example, when the interpreter sees the word print, it prints to the screen whatever is inside the parentheses. As you write your programs, your editor highlights different parts of your program in different ways. For example, it recognizes that print is the name of a function and displays that word in blue. It recognizes that “Hello Python world!” is not Python code and displays that phrase in orange. This feature is called syntax highlighting and is quite useful as you start to write your own programs. Variables Let’s try using a variable in hello_world.py. Add a new line at the beginning of the file, and modify the second line: message = "Hello Python world!" print(message) Run this program to see what happens. You should see the same output you saw previously: Hello Python world! We’ve added a variable named message. Every variable holds a value, which is the information associated with that variable. In this case the value is the text “Hello Python world!” Adding a variable makes a little more work for the Python interpreter. When it processes the first line, it associates the text “Hello Python world!” with the variable message. When it reaches the second line, it prints the value associated with message to the screen. Let’s expand on this program by modifying hello_world.py to print a sec- ond message. Add a blank line to hello_world.py, and then add two new lines of code: message = "Hello Python world!" print(message) message = "Hello Python Crash Course world!" print(message)

Variables and Simple Data Types 21 Now when you run hello_world.py, you should see two lines of output: Hello Python world! Hello Python Crash Course world! You can change the value of a variable in your program at any time, and Python will always keep track of its current value. Naming and Using Variables When you’re using variables in Python, you need to adhere to a few rules and guidelines. Breaking some of these rules will cause errors; other guide- lines just help you write code that’s easier to read and understand. Be sure to keep the following variable rules in mind: • Variable names can contain only letters, numbers, and underscores. They can start with a letter or an underscore, but not with a number. For instance, you can call a variable message_1 but not 1_message. • Spaces are not allowed in variable names, but underscores can be used to separate words in variable names. For example, greeting_message works, but greeting message will cause errors. • Avoid using Python keywords and function names as variable names; that is, do not use words that Python has reserved for a particular pro- grammatic purpose, such as the word print. (See “Python Keywords and Built-in Functions” on page 489.) • Variable names should be short but descriptive. For example, name is better than n, student_name is better than s_n, and name_length is better than length_of_persons_name. • Be careful when using the lowercase letter l and the uppercase letter O because they could be confused with the numbers 1 and 0. It can take some practice to learn how to create good variable names, especially as your programs become more interesting and complicated. As you write more programs and start to read through other people’s code, you’ll get better at coming up with meaningful names. n o t e The Python variables you’re using at this point should be lowercase. You won’t get errors if you use uppercase letters, but it’s a good idea to avoid using them for now. Avoiding Name Errors When Using Variables Every programmer makes mistakes, and most make mistakes every day. Although good programmers might create errors, they also know how to respond to those errors efficiently. Let’s look at an error you’re likely to make early on and learn how to fix it.

22 Chapter 2 We’ll write some code that generates an error on purpose. Enter the following code, including the misspelled word mesage shown in bold: message = "Hello Python Crash Course reader!" print(mesage) When an error occurs in your program, the Python interpreter does its best to help you figure out where the problem is. The interpreter provides a traceback when a program cannot run successfully. A traceback is a record of where the interpreter ran into trouble when trying to execute your code. Here’s an example of the traceback that Python provides after you’ve acci- dentally misspelled a variable’s name: Traceback (most recent call last): u File "hello_world.py", line 2, in <module> v print(mesage) w NameError: name 'mesage' is not defined The output at u reports that an error occurs in line 2 of the file hello_world.py. The interpreter shows this line to help us spot the error quickly v and tells us what kind of error it found w. In this case it found a name error and reports that the variable being printed, mesage, has not been defined. Python can’t identify the variable name provided. A name error usually means we either forgot to set a variable’s value before using it, or we made a spelling mistake when entering the variable’s name. Of course, in this example we omitted the letter s in the variable name message in the second line. The Python interpreter doesn’t spellcheck your code, but it does ensure that variable names are spelled consistently. For example, watch what happens when we spell message incorrectly in another place in the code as well: mesage = "Hello Python Crash Course reader!" print(mesage) In this case, the program runs successfully! Hello Python Crash Course reader! Computers are strict, but they disregard good and bad spelling. As a result, you don’t need to consider English spelling and grammar rules when you’re trying to create variable names and writing code. Many programming errors are simple, single-character typos in one line of a program. If you’re spending a long time searching for one of these errors, know that you’re in good company. Many experienced and talented programmers spend hours hunting down these kinds of tiny errors. Try to laugh about it and move on, knowing it will happen frequently throughout your programming life.

Variables and Simple Data Types 23 n o t e The best way to understand new programming concepts is to try using them in your programs. If you get stuck while working on an exercise in this book, try doing some- thing else for a while. If you’re still stuck, review the relevant part of that chapter. If you still need help, see the suggestions in Appendix C. try It yourse lf Write a separate program to accomplish each of these exercises Save each program with a filename that follows standard Python conventions, using lowercase letters and underscores, such as simple_message.py and simple_messages.py 2-1. Simple Message: Store a message in a variable, and then print that message 2-2. Simple Messages: Store a message in a variable, and print that message Then change the value of your variable to a new message, and print the new message strings Because most programs define and gather some sort of data, and then do something useful with it, it helps to classify different types of data. The first data type we’ll look at is the string. Strings are quite simple at first glance, but you can use them in many different ways. A string is simply a series of characters. Anything inside quotes is con- sidered a string in Python, and you can use single or double quotes around your strings like this: "This is a string." 'This is also a string.' This flexibility allows you to use quotes and apostrophes within your strings: 'I told my friend, "Python is my favorite language!"' "The language 'Python' is named after Monty Python, not the snake." "One of Python's strengths is its diverse and supportive community." Let’s explore some of the ways you can use strings.

24 Chapter 2 Changing Case in a String with Methods One of the simplest tasks you can do with strings is change the case of the words in a string. Look at the following code, and try to determine what’s happening: name.py name = "ada lovelace" print(name.title()) Save this file as name.py, and then run it. You should see this output: Ada Lovelace In this example, the lowercase string "ada lovelace" is stored in the vari- able name. The method title() appears after the variable in the print() state- ment. A method is an action that Python can perform on a piece of data. The dot (.) after name in name.title() tells Python to make the title() method act on the variable name. Every method is followed by a set of parentheses, because methods often need additional information to do their work. That information is provided inside the parentheses. The title() function doesn’t need any additional information, so its parentheses are empty. title() displays each word in titlecase, where each word begins with a capital letter. This is useful because you’ll often want to think of a name as a piece of information. For example, you might want your program to recog- nize the input values Ada, ADA, and ada as the same name, and display all of them as Ada. Several other useful methods are available for dealing with case as well. For example, you can change a string to all uppercase or all lowercase letters like this: name = "Ada Lovelace" print(name.upper()) print(name.lower()) This will display the following: ADA LOVELACE ada lovelace The lower() method is particularly useful for storing data. Many times you won’t want to trust the capitalization that your users provide, so you’ll convert strings to lowercase before storing them. Then when you want to display the information, you’ll use the case that makes the most sense for each string.

Variables and Simple Data Types 25 Combining or Concatenating Strings It’s often useful to combine strings. For example, you might want to store a first name and a last name in separate variables, and then combine them when you want to display someone’s full name: first_name = "ada" last_name = "lovelace" u full_name = first_name + " " + last_name print(full_name) Python uses the plus symbol (+) to combine strings. In this example, we use + to create a full name by combining a first_name, a space, and a last_name u, giving this result: ada lovelace This method of combining strings is called concatenation. You can use concatenation to compose complete messages using the information you’ve stored in a variable. Let’s look at an example: first_name = "ada" last_name = "lovelace" full_name = first_name + " " + last_name u print("Hello, " + full_name.title() + "!") Here, the full name is used at u in a sentence that greets the user, and the title() method is used to format the name appropriately. This code returns a simple but nicely formatted greeting: Hello, Ada Lovelace! You can use concatenation to compose a message and then store the entire message in a variable: first_name = "ada" last_name = "lovelace" full_name = first_name + " " + last_name u message = "Hello, " + full_name.title() + "!" v print(message) This code displays the message “Hello, Ada Lovelace!” as well, but stor- ing the message in a variable at u makes the final print statement at v much simpler.

26 Chapter 2 Adding Whitespace to Strings with Tabs or Newlines In programming, whitespace refers to any nonprinting character, such as spaces, tabs, and end-of-line symbols. You can use whitespace to organize your output so it’s easier for users to read. To add a tab to your text, use the character combination \t as shown at u: >>> print("Python") Python u >>> print("\tPython") Python To add a newline in a string, use the character combination \n: >>> print("Languages:\nPython\nC\nJavaScript") Languages: Python C JavaScript You can also combine tabs and newlines in a single string. The string "\n\t" tells Python to move to a new line, and start the next line with a tab. The following example shows how you can use a one-line string to generate four lines of output: >>> print("Languages:\n\tPython\n\tC\n\tJavaScript") Languages: Python C JavaScript Newlines and tabs will be very useful in the next two chapters when you start to produce many lines of output from just a few lines of code. Stripping Whitespace Extra whitespace can be confusing in your programs. To programmers 'python' and 'python ' look pretty much the same. But to a program, they are two different strings. Python detects the extra space in 'python ' and considers it significant unless you tell it otherwise. It’s important to think about whitespace, because often you’ll want to compare two strings to determine whether they are the same. For example, one important instance might involve checking people’s usernames when they log in to a website. Extra whitespace can be confusing in much simpler situations as well. Fortunately, Python makes it easy to eliminate extraneous whitespace from data that people enter. Python can look for extra whitespace on the right and left sides of a string. To ensure that no whitespace exists at the right end of a string, use the rstrip() method.

Variables and Simple Data Types 27 u >>> favorite_language = 'python ' v >>> favorite_language 'python ' w >>> favorite_language.rstrip() 'python' x >>> favorite_language 'python ' The value stored in favorite_language at u contains extra whitespace at the end of the string. When you ask Python for this value in a terminal session, you can see the space at the end of the value v. When the rstrip() method acts on the variable favorite_language at w, this extra space is removed. However, it is only removed temporarily. If you ask for the value of favorite_language again, you can see that the string looks the same as when it was entered, including the extra whitespace x. To remove the whitespace from the string permanently, you have to store the stripped value back into the variable: >>> favorite_language = 'python ' u >>> favorite_language = favorite_language.rstrip() >>> favorite_language 'python' To remove the whitespace from the string, you strip the whitespace from the right side of the string and then store that value back in the origi- nal variable, as shown at u. Changing a variable’s value and then storing the new value back in the original variable is done often in programming. This is how a variable’s value can change as a program is executed or in response to user input. You can also strip whitespace from the left side of a string using the lstrip() method or strip whitespace from both sides at once using strip(): u >>> favorite_language = ' python ' v >>> favorite_language.rstrip() ' python' w >>> favorite_language.lstrip() 'python ' x >>> favorite_language.strip() 'python' In this example, we start with a value that has whitespace at the begin- ning and the end u. We then remove the extra space from the right side at v, from the left side at w, and from both sides at x. Experimenting with these stripping functions can help you become familiar with manipulating strings. In the real world, these stripping functions are used most often to clean up user input before it’s stored in a program.

28 Chapter 2 Avoiding Syntax Errors with Strings One kind of error that you might see with some regularity is a syntax error. A syntax error occurs when Python doesn’t recognize a section of your pro- gram as valid Python code. For example, if you use an apostrophe within single quotes, you’ll produce an error. This happens because Python inter- prets everything between the first single quote and the apostrophe as a string. It then tries to interpret the rest of the text as Python code, which causes errors. Here’s how to use single and double quotes correctly. Save this program as apostrophe.py and then run it: apostrophe.py message = "One of Python's strengths is its diverse community." print(message) The apostrophe appears inside a set of double quotes, so the Python interpreter has no trouble reading the string correctly: One of Python's strengths is its diverse community. However, if you use single quotes, Python can’t identify where the string should end: message = 'One of Python's strengths is its diverse community.' print(message) You’ll see the following output: File "apostrophe.py", line 1 message = 'One of Python's strengths is its diverse community.' ^u SyntaxError: invalid syntax In the output you can see that the error occurs at u right after the second single quote. This syntax error indicates that the interpreter doesn’t recognize something in the code as valid Python code. Errors can come from a variety of sources, and I’ll point out some common ones as they arise. You might see syntax errors often as you learn to write proper Python code. Syntax errors are also the least specific kind of error, so they can be difficult and frustrating to identify and correct. If you get stuck on a particularly stub- born error, see the suggestions in Appendix C. n o t e Your editor’s syntax highlighting feature should help you spot some syntax errors quickly as you write your programs. If you see Python code highlighted as if it’s English or English highlighted as if it’s Python code, you probably have a mis- matched quotation mark somewhere in your file.

Variables and Simple Data Types 29 Printing in Python 2 The print statement has a slightly different syntax in Python 2: >>> python2.7 >>> print "Hello Python 2.7 world!" Hello Python 2.7 world! Parentheses are not needed around the phrase you want to print in Python 2. Technically, print is a function in Python 3, which is why it needs parentheses. Some Python 2 print statements do include paren- theses, but the behavior can be a little different than what you’ll see in Python 3. Basically, when you’re looking at code written in Python 2, expect to see some print statements with parentheses and some without. try It yourse lf Save each of the following exercises as a separate file with a name like name_cases.py If you get stuck, take a break or see the suggestions in Appendix C 2-3. Personal Message: Store a person’s name in a variable, and print a mes- sage to that person Your message should be simple, such as, “Hello Eric, would you like to learn some Python today?” 2-4. Name Cases: Store a person’s name in a variable, and then print that per- son’s name in lowercase, uppercase, and titlecase 2-5. Famous Quote: Find a quote from a famous person you admire Print the quote and the name of its author Your output should look something like the following, including the quotation marks: Albert Einstein once said, “A person who never made a mistake never tried anything new.” 2-6. Famous Quote 2: Repeat Exercise 2-5, but this time store the famous per- son’s name in a variable called famous_person Then compose your message and store it in a new variable called message Print your message 2-7. Stripping Names: Store a person’s name, and include some whitespace characters at the beginning and end of the name Make sure you use each character combination, "\t" and "\n", at least once Print the name once, so the whitespace around the name is displayed Then print the name using each of the three stripping functions, lstrip(), rstrip(), and strip()

30 Chapter 2 numbers Numbers are used quite often in programming to keep score in games, rep- resent data in visualizations, store information in web applications, and so on. Python treats numbers in several different ways, depending on how they are being used. Let’s first look at how Python manages integers, because they are the simplest to work with. Integers You can add (+), subtract (-), multiply (*), and divide (/) integers in Python. >>> 2 + 3 5 >>> 3 - 2 1 >>> 2 * 3 6 >>> 3 / 2 1.5 In a terminal session, Python simply returns the result of the operation. Python uses two multiplication symbols to represent exponents: >>> 3 ** 2 9 >>> 3 ** 3 27 >>> 10 ** 6 1000000 Python supports the order of operations too, so you can use multiple operations in one expression. You can also use parentheses to modify the order of operations so Python can evaluate your expression in the order you specify. For example: >>> 2 + 3*4 14 >>> (2 + 3) * 4 20 The spacing in these examples has no effect on how Python evaluates the expressions; it simply helps you more quickly spot the operations that have priority when you’re reading through the code. Floats Python calls any number with a decimal point a float. This term is used in most programming languages, and it refers to the fact that a decimal point can appear at any position in a number. Every programming language must

Variables and Simple Data Types 31 be carefully designed to properly manage decimal numbers so numbers behave appropriately no matter where the decimal point appears. For the most part, you can use decimals without worrying about how they behave. Simply enter the numbers you want to use, and Python will most likely do what you expect: >>> 0.1 + 0.1 0.2 >>> 0.2 + 0.2 0.4 >>> 2 * 0.1 0.2 >>> 2 * 0.2 0.4 But be aware that you can sometimes get an arbitrary number of deci- mal places in your answer: >>> 0.2 + 0.1 0.30000000000000004 >>> 3 * 0.1 0.30000000000000004 This happens in all languages and is of little concern. Python tries to find a way to represent the result as precisely as possible, which is sometimes difficult given how computers have to represent numbers internally. Just ignore the extra decimal places for now; you’ll learn ways to deal with the extra places when you need to in the projects in Part II. Avoiding Type Errors with the str() Function Often, you’ll want to use a variable’s value within a message. For example, say you want to wish someone a happy birthday. You might write code like this: birthday.py age = 23 message = "Happy " + age + "rd Birthday!" print(message) You might expect this code to print the simple birthday greeting, Happy 23rd birthday! But if you run this code, you’ll see that it generates an error: Traceback (most recent call last): File "birthday.py", line 2, in <module> message = "Happy " + age + "rd Birthday!" u TypeError: Can't convert 'int' object to str implicitly This is a type error. It means Python can’t recognize the kind of informa- tion you’re using. In this example Python sees at u that you’re using a vari- able that has an integer value (int), but it’s not sure how to interpret that

32 Chapter 2 value. Python knows that the variable could represent either the numerical value 23 or the characters 2 and 3. When you use integers within strings like this, you need to specify explicitly that you want Python to use the inte- ger as a string of characters. You can do this by wrapping the variable in the str() function, which tells Python to represent non-string values as strings: age = 23 message = "Happy " + str(age) + "rd Birthday!" print(message) Python now knows that you want to convert the numerical value 23 to a string and display the characters 2 and 3 as part of the birthday message. Now you get the message you were expecting, without any errors: Happy 23rd Birthday! Working with numbers in Python is straightforward most of the time. If you’re getting unexpected results, check whether Python is interpreting your numbers the way you want it to, either as a numerical value or as a string value. Integers in Python 2 Python 2 returns a slightly different result when you divide two integers: >>> python2.7 >>> 3 / 2 1 Instead of 1.5, Python returns 1. Division of integers in Python 2 results in an integer with the remainder truncated. Note that the result is not a rounded integer; the remainder is simply omitted. To avoid this behavior in Python 2, make sure that at least one of the numbers is a float. By doing so, the result will be a float as well: >>> 3 / 2 1 >>> 3.0 / 2 1.5 >>> 3 / 2.0 1.5 >>> 3.0 / 2.0 1.5 This division behavior is a common source of confusion when people who are used to Python 3 start using Python 2, or vice versa. If you use or create code that mixes integers and floats, watch out for irregular behavior.

Variables and Simple Data Types 33 try It yourse lf 2-8. Number Eight: Write addition, subtraction, multiplication, and division operations that each result in the number 8 Be sure to enclose your operations in print statements to see the results You should create four lines that look like this: print(5 + 3) Your output should simply be four lines with the number 8 appearing once on each line 2-9. Favorite Number: Store your favorite number in a variable Then, using that variable, create a message that reveals your favorite number Print that message Comments Comments are an extremely useful feature in most programming languages. Everything you’ve written in your programs so far is Python code. As your programs become longer and more complicated, you should add notes within your programs that describe your overall approach to the problem you’re solving. A comment allows you to write notes in English within your programs. How Do You Write Comments? In Python, the hash mark (#) indicates a comment. Anything following a hash mark in your code is ignored by the Python interpreter. For example: comment.py # Say hello to everyone. print("Hello Python people!") Python ignores the first line and executes the second line. Hello Python people! What Kind of Comments Should You Write? The main reason to write comments is to explain what your code is sup- posed to do and how you are making it work. When you’re in the middle of working on a project, you understand how all of the pieces fit together. But when you return to a project after some time away, you’ll likely have forgot- ten some of the details. You can always study your code for a while and fig- ure out how segments were supposed to work, but writing good comments can save you time by summarizing your overall approach in clear English.

34 Chapter 2 If you want to become a professional programmer or collaborate with other programmers, you should write meaningful comments. Today, most software is written collaboratively, whether by a group of employees at one company or a group of people working together on an open source project. Skilled programmers expect to see comments in code, so it’s best to start adding descriptive comments to your programs now. Writing clear, concise comments in your code is one of the most beneficial habits you can form as a new programmer. When you’re determining whether to write a comment, ask yourself if you had to consider several approaches before coming up with a reasonable way to make something work; if so, write a comment about your solution. It’s much easier to delete extra comments later on than it is to go back and write comments for a sparsely commented program. From now on, I’ll use comments in examples throughout this book to help explain sections of code. try It yourse lf 2-10. Adding Comments: Choose two of the programs you’ve written, and add at least one comment to each If you don’t have anything specific to write because your programs are too simple at this point, just add your name and the current date at the top of each program file Then write one sentence describing what the program does the zen of Python For a long time, the programming language Perl was the mainstay of the Internet. Most interactive websites in the early days were powered by Perl scripts. The Perl community’s motto at the time was, “There’s more than one way to do it.” People liked this mind-set for a while, because the flex- ibility written into the language made it possible to solve most problems in a variety of ways. This approach was acceptable while working on your own projects, but eventually people realized that the emphasis on flexibility made it difficult to maintain large projects over long periods of time. It was difficult, tedious, and time-consuming to review code and try to figure out what someone else was thinking when they were solving a complex problem. Experienced Python programmers will encourage you to avoid com- plexity and aim for simplicity whenever possible. The Python community’s philosophy is contained in “The Zen of Python” by Tim Peters. You can access this brief set of principles for writing good Python code by enter- ing import this into your interpreter. I won’t reproduce the entire “Zen of

Variables and Simple Data Types 35 Python” here, but I’ll share a few lines to help you understand why they should be important to you as a beginning Python programmer. >>> import this The Zen of Python, by Tim Peters Beautiful is better than ugly. Python programmers embrace the notion that code can be beautiful and elegant. In programming, people solve problems. Programmers have always respected well-designed, efficient, and even beautiful solutions to problems. As you learn more about Python and use it to write more code, someone might look over your shoulder one day and say, “Wow, that’s some beautiful code!” Simple is better than complex. If you have a choice between a simple and a complex solution, and both work, use the simple solution. Your code will be easier to maintain, and it will be easier for you and others to build on that code later on. Complex is better than complicated. Real life is messy, and sometimes a simple solution to a problem is unat- tainable. In that case, use the simplest solution that works. Readability counts. Even when your code is complex, aim to make it readable. When you’re working on a project that involves complex coding, focus on writing infor- mative comments for that code. There should be one-- and preferably only one --obvious way to do it. If two Python programmers are asked to solve the same problem, they should come up with fairly compatible solutions. This is not to say there’s no room for creativity in programming. On the contrary! But much of pro- gramming consists of using small, common approaches to simple situations within a larger, more creative project. The nuts and bolts of your programs should make sense to other Python programmers. Now is better than never. You could spend the rest of your life learning all the intricacies of Python and of programming in general, but then you’d never complete any projects. Don’t try to write perfect code; write code that works, and then decide whether to improve your code for that project or move on to some- thing new.

36 Chapter 2 As you continue to the next chapter and start digging into more involved topics, try to keep this philosophy of simplicity and clarity in mind. Experienced programmers will respect your code more and will be happy to give you feedback and collaborate with you on interesting projects. try It yourse lf 2-11. Zen of Python: Enter import this into a Python terminal session and skim through the additional principles summary In this chapter you learned to work with variables. You learned to use descriptive variable names and how to resolve name errors and syn- tax errors when they arise. You learned what strings are and how to display strings using lowercase, uppercase, and titlecase. You started using whitespace to organize output neatly, and you learned to strip unneeded whitespace from different parts of a string. You started working with integers and floats, and you read about some unexpected behavior to watch out for when working with numerical data. You also learned to write explanatory comments to make your code easier for you and others to read. Finally, you read about the philosophy of keeping your code as simple as possible, whenever possible. In Chapter 3 you’ll learn to store collections of information in variables called lists. You’ll learn to work through a list, manipulating any informa- tion in that list.

3I n t r o D u C I n g l I s t s In this chapter and the next you’ll learn what lists are and how to start working with the elements in a list. Lists allow you to store sets of information in one place, whether you have just a few items or millions of items. Lists are one of Python’s most powerful features readily acces- sible to new programmers, and they tie together many important concepts in programming. what Is a list? A list is a collection of items in a particular order. You can make a list that includes the letters of the alphabet, the digits from 0–9, or the names of all the people in your family. You can put anything you want into a list, and

38 Chapter 3 the items in your list don’t have to be related in any particular way. Because a list usually contains more than one element, it’s a good idea to make the name of your list plural, such as letters, digits, or names. In Python, square brackets ([]) indicate a list, and individual elements in the list are separated by commas. Here’s a simple example of a list that contains a few kinds of bicycles: bicycles.py bicycles = ['trek', 'cannondale', 'redline', 'specialized'] print(bicycles) If you ask Python to print a list, Python returns its representation of the list, including the square brackets: ['trek', 'cannondale', 'redline', 'specialized'] Because this isn’t the output you want your users to see, let’s learn how to access the individual items in a list. Accessing Elements in a List Lists are ordered collections, so you can access any element in a list by telling Python the position, or index, of the item desired. To access an ele- ment in a list, write the name of the list followed by the index of the item enclosed in square brackets. For example, let’s pull out the first bicycle in the list bicycles: bicycles = ['trek', 'cannondale', 'redline', 'specialized'] u print(bicycles[0]) The syntax for this is shown at u. When we ask for a single item from a list, Python returns just that element without square brackets or quotation marks: trek This is the result you want your users to see—clean, neatly formatted output. You can also use the string methods from Chapter 2 on any element in a list. For example, you can format the element 'trek' more neatly by using the title() method: bicycles = ['trek', 'cannondale', 'redline', 'specialized'] print(bicycles[0].title()) This example produces the same output as the preceding example except 'Trek' is capitalized.

Introducing Lists 39 Index Positions Start at 0, Not 1 Python considers the first item in a list to be at position 0, not position 1. This is true of most programming languages, and the reason has to do with how the list operations are implemented at a lower level. If you’re receiving unexpected results, determine whether you are making a simple off-by-one error. The second item in a list has an index of 1. Using this simple counting system, you can get any element you want from a list by subtracting one from its position in the list. For instance, to access the fourth item in a list, you request the item at index 3. The following asks for the bicycles at index 1 and index 3: bicycles = ['trek', 'cannondale', 'redline', 'specialized'] print(bicycles[1]) print(bicycles[3]) This code returns the second and fourth bicycles in the list: cannondale specialized Python has a special syntax for accessing the last element in a list. By ask- ing for the item at index -1, Python always returns the last item in the list: bicycles = ['trek', 'cannondale', 'redline', 'specialized'] print(bicycles[-1]) This code returns the value 'specialized'. This syntax is quite useful, because you’ll often want to access the last items in a list without knowing exactly how long the list is. This convention extends to other negative index values as well. The index -2 returns the second item from the end of the list, the index -3 returns the third item from the end, and so forth. Using Individual Values from a List You can use individual values from a list just as you would any other vari- able. For example, you can use concatenation to create a message based on a value from a list. Let’s try pulling the first bicycle from the list and composing a message using that value. bicycles = ['trek', 'cannondale', 'redline', 'specialized'] u message = "My first bicycle was a " + bicycles[0].title() + "." print(message)

40 Chapter 3 At u, we build a sentence using the value at bicycles[0] and store it in the variable message. The output is a simple sentence about the first bicycle in the list: My first bicycle was a Trek. try It yourse lf Try these short programs to get some firsthand experience with Python’s lists You might want to create a new folder for each chapter’s exercises to keep them organized 3-1. Names: Store the names of a few of your friends in a list called names Print each person’s name by accessing each element in the list, one at a time 3-2. Greetings: Start with the list you used in Exercise 3-1, but instead of just printing each person’s name, print a message to them The text of each mes- sage should be the same, but each message should be personalized with the person’s name 3-3. Your Own List: Think of your favorite mode of transportation, such as a motorcycle or a car, and make a list that stores several examples Use your list to print a series of statements about these items, such as “I would like to own a Honda motorcycle ” Changing, adding, and removing elements Most lists you create will be dynamic, meaning you’ll build a list and then add and remove elements from it as your program runs its course. For example, you might create a game in which a player has to shoot aliens out of the sky. You could store the initial set of aliens in a list and then remove an alien from the list each time one is shot down. Each time a new alien appears on the screen, you add it to the list. Your list of aliens will decrease and increase in length throughout the course of the game. Modifying Elements in a List The syntax for modifying an element is similar to the syntax for accessing an element in a list. To change an element, use the name of the list followed by the index of the element you want to change, and then provide the new value you want that item to have.

Introducing Lists 41 For example, let’s say we have a list of motorcycles, and the first item in the list is 'honda'. How would we change the value of this first item? motorcycles.py u motorcycles = ['honda', 'yamaha', 'suzuki'] print(motorcycles) v motorcycles[0] = 'ducati' print(motorcycles) The code at u defines the original list, with 'honda' as the first element. The code at v changes the value of the first item to 'ducati'. The output shows that the first item has indeed been changed, and the rest of the list stays the same: ['honda', 'yamaha', 'suzuki'] ['ducati', 'yamaha', 'suzuki'] You can change the value of any item in a list, not just the first item. Adding Elements to a List You might want to add a new element to a list for many reasons. For example, you might want to make new aliens appear in a game, add new data to a visualization, or add new registered users to a website you’ve built. Python provides several ways to add new data to existing lists. appending Elements to the End of a List The simplest way to add a new element to a list is to append the item to the list. When you append an item to a list, the new element is added to the end of the list. Using the same list we had in the previous example, we’ll add the new element 'ducati' to the end of the list: motorcycles = ['honda', 'yamaha', 'suzuki'] print(motorcycles) u motorcycles.append('ducati') print(motorcycles) The append() method at u adds 'ducati' to the end of the list without affecting any of the other elements in the list: ['honda', 'yamaha', 'suzuki'] ['honda', 'yamaha', 'suzuki', 'ducati']

42 Chapter 3 The append() method makes it easy to build lists dynamically. For example, you can start with an empty list and then add items to the list using a series of append() statements. Using an empty list, let’s add the ele- ments 'honda', 'yamaha', and 'suzuki' to the list: motorcycles = [] motorcycles.append('honda') motorcycles.append('yamaha') motorcycles.append('suzuki') print(motorcycles) The resulting list looks exactly the same as the lists in the previous examples: ['honda', 'yamaha', 'suzuki'] Building lists this way is very common, because you often won’t know the data your users want to store in a program until after the program is running. To put your users in control, start by defining an empty list that will hold the users’ values. Then append each new value provided to the list you just created. Inserting Elements into a List You can add a new element at any position in your list by using the insert() method. You do this by specifying the index of the new element and the value of the new item. motorcycles = ['honda', 'yamaha', 'suzuki'] u motorcycles.insert(0, 'ducati') print(motorcycles) In this example, the code at u inserts the value 'ducati' at the begin- ning of the list. The insert() method opens a space at position 0 and stores the value 'ducati' at that location. This operation shifts every other value in the list one position to the right: ['ducati', 'honda', 'yamaha', 'suzuki'] Removing Elements from a List Often, you’ll want to remove an item or a set of items from a list. For example, when a player shoots down an alien from the sky, you’ll most likely want to remove it from the list of active aliens. Or when a user

Introducing Lists 43 decides to cancel their account on a web application you created, you’ll want to remove that user from the list of active users. You can remove an item according to its position in the list or according to its value. removing an Item Using the del Statement If you know the position of the item you want to remove from a list, you can use the del statement. motorcycles = ['honda', 'yamaha', 'suzuki'] print(motorcycles) u del motorcycles[0] print(motorcycles) The code at u uses del to remove the first item, 'honda', from the list of motorcycles: ['honda', 'yamaha', 'suzuki'] ['yamaha', 'suzuki'] You can remove an item from any position in a list using the del state- ment if you know its index. For example, here’s how to remove the second item, 'yamaha', in the list: motorcycles = ['honda', 'yamaha', 'suzuki'] print(motorcycles) del motorcycles[1] print(motorcycles) The second motorcycle is deleted from the list: ['honda', 'yamaha', 'suzuki'] ['honda', 'suzuki'] In both examples, you can no longer access the value that was removed from the list after the del statement is used. removing an Item Using the pop() Method Sometimes you’ll want to use the value of an item after you remove it from a list. For example, you might want to get the x and y position of an alien that was just shot down, so you can draw an explosion at that position. In a web application, you might want to remove a user from a list of active members and then add that user to a list of inactive members. The pop() method removes the last item in a list, but it lets you work with that item after removing it. The term pop comes from thinking of a list as a stack of items and popping one item off the top of the stack. In this analogy, the top of a stack corresponds to the end of a list.

44 Chapter 3 Let’s pop a motorcycle from the list of motorcycles: u motorcycles = ['honda', 'yamaha', 'suzuki'] print(motorcycles) v popped_motorcycle = motorcycles.pop() w print(motorcycles) x print(popped_motorcycle) We start by defining and printing the list motorcycles at u. At v we pop a value from the list and store that value in the variable popped_motorcycle. We print the list at w to show that a value has been removed from the list. Then we print the popped value at x to prove that we still have access to the value that was removed. The output shows that the value 'suzuki' was removed from the end of the list and is now stored in the variable popped_motorcycle: ['honda', 'yamaha', 'suzuki'] ['honda', 'yamaha'] suzuki How might this pop() method be useful? Imagine that the motorcycles in the list are stored in chronological order according to when we owned them. If this is the case, we can use the pop() method to print a statement about the last motorcycle we bought: motorcycles = ['honda', 'yamaha', 'suzuki'] last_owned = motorcycles.pop() print("The last motorcycle I owned was a " + last_owned.title() + ".") The output is a simple sentence about the most recent motorcycle we owned: The last motorcycle I owned was a Suzuki. Popping Items from any Position in a List You can actually use pop() to remove an item in a list at any position by including the index of the item you want to remove in parentheses. motorcycles = ['honda', 'yamaha', 'suzuki'] u first_owned = motorcycles.pop(0) v print('The first motorcycle I owned was a ' + first_owned.title() + '.')

Introducing Lists 45 We start by popping the first motorcycle in the list at u, and then we print a message about that motorcycle at v. The output is a simple sentence describing the first motorcycle I ever owned: The first motorcycle I owned was a Honda. Remember that each time you use pop(), the item you work with is no longer stored in the list. If you’re unsure whether to use the del statement or the pop() method, here’s a simple way to decide: when you want to delete an item from a list and not use that item in any way, use the del statement; if you want to use an item as you remove it, use the pop() method. removing an Item by Value Sometimes you won’t know the position of the value you want to remove from a list. If you only know the value of the item you want to remove, you can use the remove() method. For example, let’s say we want to remove the value 'ducati' from the list of motorcycles. motorcycles = ['honda', 'yamaha', 'suzuki', 'ducati'] print(motorcycles) u motorcycles.remove('ducati') print(motorcycles) The code at u tells Python to figure out where 'ducati' appears in the list and remove that element: ['honda', 'yamaha', 'suzuki', 'ducati'] ['honda', 'yamaha', 'suzuki'] You can also use the remove() method to work with a value that’s being removed from a list. Let’s remove the value 'ducati' and print a reason for removing it from the list: u motorcycles = ['honda', 'yamaha', 'suzuki', 'ducati'] print(motorcycles) v too_expensive = 'ducati' w motorcycles.remove(too_expensive) print(motorcycles) x print("\nA " + too_expensive.title() + " is too expensive for me.") After defining the list at u, we store the value 'ducati' in a variable called too_expensive v. We then use this variable to tell Python which value

46 Chapter 3 to remove from the list at w. At x the value 'ducati' has been removed from the list but is still stored in the variable too_expensive, allowing us to print a statement about why we removed 'ducati' from the list of motorcycles: ['honda', 'yamaha', 'suzuki', 'ducati'] ['honda', 'yamaha', 'suzuki'] A Ducati is too expensive for me. n o t e The remove() method deletes only the first occurrence of the value you specify. If there’s a possibility the value appears more than once in the list, you’ll need to use a loop to determine if all occurrences of the value have been removed. You’ll learn how to do this in Chapter 7. try It yourse lf The following exercises are a bit more complex than those in Chapter 2, but they give you an opportunity to use lists in all of the ways described 3-4. Guest List: If you could invite anyone, living or deceased, to dinner, who would you invite? Make a list that includes at least three people you’d like to invite to dinner Then use your list to print a message to each person, inviting them to dinner 3-5. Changing Guest List: You just heard that one of your guests can’t make the dinner, so you need to send out a new set of invitations You’ll have to think of someone else to invite • Start with your program from Exercise 3-4 Add a print statement at the end of your program stating the name of the guest who can’t make it • Modify your list, replacing the name of the guest who can’t make it with the name of the new person you are inviting • Print a second set of invitation messages, one for each person who is still in your list 3-6. More Guests: You just found a bigger dinner table, so now more space is available Think of three more guests to invite to dinner • Start with your program from Exercise 3-4 or Exercise 3-5 Add a print statement to the end of your program informing people that you found a bigger dinner table • Use insert() to add one new guest to the beginning of your list • Use insert() to add one new guest to the middle of your list • Use append() to add one new guest to the end of your list • Print a new set of invitation messages, one for each person in your list

Introducing Lists 47 3-7. Shrinking Guest List: You just found out that your new dinner table won’t arrive in time for the dinner, and you have space for only two guests • Start with your program from Exercise 3-6 Add a new line that prints a message saying that you can invite only two people for dinner • Use pop() to remove guests from your list one at a time until only two names remain in your list Each time you pop a name from your list, print a message to that person letting them know you’re sorry you can’t invite them to dinner • Print a message to each of the two people still on your list, letting them know they’re still invited • Use del to remove the last two names from your list, so you have an empty list Print your list to make sure you actually have an empty list at the end of your program organizing a list Often, your lists will be created in an unpredictable order, because you can’t always control the order in which your users provide their data. Although this is unavoidable in most circumstances, you’ll frequently want to present your information in a particular order. Sometimes you’ll want to preserve the original order of your list, and other times you’ll want to change the origi- nal order. Python provides a number of different ways to organize your lists, depending on the situation. Sorting a List Permanently with the sort() Method Python’s sort() method makes it relatively easy to sort a list. Imagine we have a list of cars and want to change the order of the list to store them alphabetically. To keep the task simple, let’s assume that all the values in the list are lowercase. cars.py cars = ['bmw', 'audi', 'toyota', 'subaru'] u cars.sort() print(cars) The sort() method, shown at u, changes the order of the list perma- nently. The cars are now in alphabetical order, and we can never revert to the original order: ['audi', 'bmw', 'subaru', 'toyota']

48 Chapter 3 You can also sort this list in reverse alphabetical order by passing the argument reverse=True to the sort() method. The following example sorts the list of cars in reverse alphabetical order: cars = ['bmw', 'audi', 'toyota', 'subaru'] cars.sort(reverse=True) print(cars) Again, the order of the list is permanently changed: ['toyota', 'subaru', 'bmw', 'audi'] Sorting a List Temporarily with the sorted() Function To maintain the original order of a list but present it in a sorted order, you can use the sorted() function. The sorted() function lets you display your list in a particular order but doesn’t affect the actual order of the list. Let’s try this function on the list of cars. cars = ['bmw', 'audi', 'toyota', 'subaru'] u print("Here is the original list:") print(cars) v print("\nHere is the sorted list:") print(sorted(cars)) w print("\nHere is the original list again:") print(cars) We first print the list in its original order at u and then in alphabetical order at v. After the list is displayed in the new order, we show that the list is still stored in its original order at w. Here is the original list: ['bmw', 'audi', 'toyota', 'subaru'] Here is the sorted list: ['audi', 'bmw', 'subaru', 'toyota'] x Here is the original list again: ['bmw', 'audi', 'toyota', 'subaru'] Notice that the list still exists in its original order at x after the sorted() function has been used. The sorted() function can also accept a reverse=True argument if you want to display a list in reverse alphabetical order.

Introducing Lists 49 n o t e Sorting a list alphabetically is a bit more complicated when all the values are not in lowercase. There are several ways to interpret capital letters when you’re deciding on a sort order, and specifying the exact order can be more complex than we want to deal with at this time. However, most approaches to sorting will build directly on what you learned in this section. Printing a List in Reverse Order To reverse the original order of a list, you can use the reverse() method. If we originally stored the list of cars in chronological order according to when we owned them, we could easily rearrange the list into reverse chron- ological order: cars = ['bmw', 'audi', 'toyota', 'subaru'] print(cars) cars.reverse() print(cars) Notice that reverse() doesn’t sort backward alphabetically; it simply reverses the order of the list: ['bmw', 'audi', 'toyota', 'subaru'] ['subaru', 'toyota', 'audi', 'bmw'] The reverse() method changes the order of a list permanently, but you can revert to the original order anytime by applying reverse() to the same list a second time. Finding the Length of a List You can quickly find the length of a list by using the len() function. The list in this example has four items, so its length is 4: >>> cars = ['bmw', 'audi', 'toyota', 'subaru'] >>> len(cars) 4 You’ll find len() useful when you need to identify the number of aliens that still need to be shot down in a game, determine the amount of data you have to manage in a visualization, or figure out the number of regis- tered users on a website, among other tasks. n o t e Python counts the items in a list starting with one, so you shouldn’t run into any off- by-one errors when determining the length of a list.

50 Chapter 3 try It yourse lf 3-8. Seeing the World: Think of at least five places in the world you’d like to visit • Store the locations in a list Make sure the list is not in alphabetical order • Print your list in its original order Don’t worry about printing the list neatly, just print it as a raw Python list • Use sorted() to print your list in alphabetical order without modifying the actual list • Show that your list is still in its original order by printing it • Use sorted() to print your list in reverse alphabetical order without chang- ing the order of the original list • Show that your list is still in its original order by printing it again • Use reverse() to change the order of your list Print the list to show that its order has changed • Use reverse() to change the order of your list again Print the list to show it’s back to its original order • Use sort() to change your list so it’s stored in alphabetical order Print the list to show that its order has been changed • Use sort() to change your list so it’s stored in reverse alphabetical order Print the list to show that its order has changed 3-9. Dinner Guests: Working with one of the programs from Exercises 3-4 through 3-7 (page 46), use len() to print a message indicating the number of people you are inviting to dinner 3-10. Every Function: Think of something you could store in a list For example, you could make a list of mountains, rivers, countries, cities, languages, or any- thing else you’d like Write a program that creates a list containing these items and then uses each function introduced in this chapter at least once avoiding Index errors when working with lists One type of error is common to see when you’re working with lists for the first time. Let’s say you have a list with three items, and you ask for the fourth item: motorcycles = ['honda', 'yamaha', 'suzuki'] print(motorcycles[3])

Introducing Lists 51 This example results in an index error: Traceback (most recent call last): File "motorcycles.py", line 3, in <module> print(motorcycles[3]) IndexError: list index out of range Python attempts to give you the item at index 3. But when it searches the list, no item in motorcycles has an index of 3. Because of the off-by-one nature of indexing in lists, this error is typical. People think the third item is item number 3, because they start counting at 1. But in Python the third item is number 2, because it starts indexing at 0. An index error means Python can’t figure out the index you requested. If an index error occurs in your program, try adjusting the index you’re asking for by one. Then run the program again to see if the results are correct. Keep in mind that whenever you want to access the last item in a list you use the index -1. This will always work, even if your list has changed size since the last time you accessed it: motorcycles = ['honda', 'yamaha', 'suzuki'] print(motorcycles[-1]) The index -1 always returns the last item in a list, in this case the value 'suzuki': 'suzuki' The only time this approach will cause an error is when you request the last item from an empty list: motorcycles = [] print(motorcycles[-1]) No items are in motorcycles, so Python returns another index error: Traceback (most recent call last): File "motorcyles.py", line 3, in <module> print(motorcycles[-1]) IndexError: list index out of range n o t e If an index error occurs and you can’t figure out how to resolve it, try printing your list or just printing the length of your list. Your list might look much different than you thought it did, especially if it has been managed dynamically by your program. Seeing the actual list, or the exact number of items in your list, can help you sort out such logical errors.

52 Chapter 3 try It yourse lf 3-11. Intentional Error: If you haven’t received an index error in one of your programs yet, try to make one happen Change an index in one of your pro- grams to produce an index error Make sure you correct the error before clos- ing the program summary In this chapter you learned what lists are and how to work with the indi- vidual items in a list. You learned how to define a list and how to add and remove elements. You learned to sort lists permanently and temporarily for display purposes. You also learned how to find the length of a list and how to avoid index errors when you’re working with lists. In Chapter 4 you’ll learn how to work with items in a list more effi- ciently. By looping through each item in a list using just a few lines of code you’ll be able to work efficiently, even when your list contains thousands or millions of items.

4w o r k I n g w I t h l I s t s In Chapter 3 you learned how to make a simple list, and you learned to work with the individual elements in a list. In this chap- ter you’ll learn how to loop through an entire list using just a few lines of code regardless of how long the list is. Looping allows you to take the same action, or set of actions, with every item in a list. As a result, you’ll be able to work efficiently with lists of any length, including those with thousands or even millions of items. looping through an entire list You’ll often want to run through all entries in a list, performing the same task with each item. For example, in a game you might want to move every element on the screen by the same amount, or in a list of numbers you might want to perform the same statistical operation on every element. Or perhaps you’ll want to display each headline from a list of articles on a web- site. When you want to do the same action with every item in a list, you can use Python’s for loop.

54 Chapter 4 Let’s say we have a list of magicians’ names, and we want to print out each name in the list. We could do this by retrieving each name from the list individually, but this approach could cause several problems. For one, it would be repetitive to do this with a long list of names. Also, we’d have to change our code each time the list’s length changed. A for loop avoids both of these issues by letting Python manage these issues internally. Let’s use a for loop to print out each name in a list of magicians: magicians.py u magicians = ['alice', 'david', 'carolina'] v for magician in magicians: w print(magician) We begin by defining a list at u, just as we did in Chapter 3. At v, we define a for loop. This line tells Python to pull a name from the list magicians, and store it in the variable magician. At w we tell Python to print the name that was just stored in magician. Python then repeats lines v and w, once for each name in the list. It might help to read this code as “For every magician in the list of magicians, print the magician’s name.” The output is a simple printout of each name in the list: alice david carolina A Closer Look at Looping The concept of looping is important because it’s one of the most common ways a computer automates repetitive tasks. For example, in a simple loop like we used in magicians.py, Python initially reads the first line of the loop: for magician in magicians: This line tells Python to retrieve the first value from the list magicians and store it in the variable magician. This first value is 'alice'. Python then reads the next line: print(magician) Python prints the current value of magician, which is still 'alice'. Because the list contains more values, Python returns to the first line of the loop: for magician in magicians: Python retrieves the next name in the list, 'david', and stores that value in magician. Python then executes the line: print(magician)

Working with Lists 55 Python prints the current value of magician again, which is now 'david'. Python repeats the entire loop once more with the last value in the list, 'carolina'. Because no more values are in the list, Python moves on to the next line in the program. In this case nothing comes after the for loop, so the program simply ends. When you’re using loops for the first time, keep in mind that the set of steps is repeated once for each item in the list, no matter how many items are in the list. If you have a million items in your list, Python repeats these steps a million times—and usually very quickly. Also keep in mind when writing your own for loops that you can choose any name you want for the temporary variable that holds each value in the list. However, it’s helpful to choose a meaningful name that represents a single item from the list. For example, here’s a good way to start a for loop for a list of cats, a list of dogs, and a general list of items: for cat in cats: for dog in dogs: for item in list_of_items: These naming conventions can help you follow the action being done on each item within a for loop. Using singular and plural names can help you identify whether a section of code is working with a single element from the list or the entire list. Doing More Work Within a for Loop You can do just about anything with each item in a for loop. Let’s build on the previous example by printing a message to each magician, telling them that they performed a great trick: magicians = ['alice', 'david', 'carolina'] for magician in magicians: u print(magician.title() + ", that was a great trick!") The only difference in this code is at u where we compose a message to each magician, starting with that magician’s name. The first time through the loop the value of magician is 'alice', so Python starts the first message with the name 'Alice'. The second time through the message will begin with 'David', and the third time through the message will begin with 'Carolina'. The output shows a personalized message for each magician in the list: Alice, that was a great trick! David, that was a great trick! Carolina, that was a great trick! You can also write as many lines of code as you like in the for loop. Every indented line following the line for magician in magicians is con- sidered inside the loop, and each indented line is executed once for each

56 Chapter 4 value in the list. Therefore, you can do as much work as you like with each value in the list. Let’s add a second line to our message, telling each magician that we’re looking forward to their next trick: magicians = ['alice', 'david', 'carolina'] for magician in magicians: print(magician.title() + ", that was a great trick!") u print("I can't wait to see your next trick, " + magician.title() + ".\n") Because we have indented both print statements, each line will be exe- cuted once for every magician in the list. The newline ("\n") in the second print statement u inserts a blank line after each pass through the loop. This creates a set of messages that are neatly grouped for each person in the list: Alice, that was a great trick! I can't wait to see your next trick, Alice. David, that was a great trick! I can't wait to see your next trick, David. Carolina, that was a great trick! I can't wait to see your next trick, Carolina. You can use as many lines as you like in your for loops. In practice you’ll often find it useful to do a number of different operations with each item in a list when you use a for loop. Doing Something After a for Loop What happens once a for loop has finished executing? Usually, you’ll want to summarize a block of output or move on to other work that your pro- gram must accomplish. Any lines of code after the for loop that are not indented are executed once without repetition. Let’s write a thank you to the group of magicians as a whole, thanking them for putting on an excellent show. To display this group message after all of the individual messages have been printed, we place the thank you message after the for loop without indentation: magicians = ['alice', 'david', 'carolina'] for magician in magicians: print(magician.title() + ", that was a great trick!") print("I can't wait to see your next trick, " + magician.title() + ".\n") u print("Thank you, everyone. That was a great magic show!")

Working with Lists 57 The first two print statements are repeated once for each magician in the list, as you saw earlier. However, because the line at u is not indented, it’s printed only once: Alice, that was a great trick! I can't wait to see your next trick, Alice. David, that was a great trick! I can't wait to see your next trick, David. Carolina, that was a great trick! I can't wait to see your next trick, Carolina. Thank you, everyone. That was a great magic show! When you’re processing data using a for loop, you’ll find that this is a good way to summarize an operation that was performed on an entire data set. For example, you might use a for loop to initialize a game by running through a list of characters and displaying each character on the screen. You might then write an unindented block after this loop that displays a Play Now button after all the characters have been drawn to the screen. avoiding Indentation errors Python uses indentation to determine when one line of code is connected to the line above it. In the previous examples, the lines that printed messages to individual magicians were part of the for loop because they were indented. Python’s use of indentation makes code very easy to read. Basically, it uses whitespace to force you to write neatly formatted code with a clear visual structure. In longer Python programs, you’ll notice blocks of code indented at a few different levels. These indentation levels help you gain a general sense of the overall program’s organization. As you begin to write code that relies on proper indentation, you’ll need to watch for a few common indentation errors. For example, people sometimes indent blocks of code that don’t need to be indented or forget to indent blocks that need to be indented. Seeing examples of these errors now will help you avoid them in the future and correct them when they do appear in your own programs. Let’s examine some of the more common indentation errors. Forgetting to Indent Always indent the line after the for statement in a loop. If you forget, Python will remind you: magicians.py magicians = ['alice', 'david', 'carolina'] for magician in magicians: u print(magician)

58 Chapter 4 The print statement at u should be indented, but it’s not. When Python expects an indented block and doesn’t find one, it lets you know which line it had a problem with. File "magicians.py", line 3 print(magician) ^ IndentationError: expected an indented block You can usually resolve this kind of indentation error by indenting the line or lines immediately after the for statement. Forgetting to Indent Additional Lines Sometimes your loop will run without any errors but won’t produce the expected result. This can happen when you’re trying to do several tasks in a loop and you forget to indent some of its lines. For example, this is what happens when we forget to indent the second line in the loop that tells each magician we’re looking forward to their next trick: magicians = ['alice', 'david', 'carolina'] for magician in magicians: print(magician.title() + ", that was a great trick!") u print("I can't wait to see your next trick, " + magician.title() + ".\n") The print statement at u is supposed to be indented, but because Python finds at least one indented line after the for statement, it doesn’t report an error. As a result, the first print statement is executed once for each name in the list because it is indented. The second print statement is not indented, so it is executed only once after the loop has finished run- ning. Because the final value of magician is 'carolina', she is the only one who receives the “looking forward to the next trick” message: Alice, that was a great trick! David, that was a great trick! Carolina, that was a great trick! I can't wait to see your next trick, Carolina. This is a logical error. The syntax is valid Python code, but the code does not produce the desired result because a problem occurs in its logic. If you expect to see a certain action repeated once for each item in a list and it’s executed only once, determine whether you need to simply indent a line or a group of lines.

Working with Lists 59 Indenting Unnecessarily If you accidentally indent a line that doesn’t need to be indented, Python informs you about the unexpected indent: hello_world.py message = "Hello Python world!" u print(message) We don’t need to indent the print statement at u, because it doesn’t belong to the line above it; hence, Python reports that error: File "hello_world.py", line 2 print(message) ^ IndentationError: unexpected indent You can avoid unexpected indentation errors by indenting only when you have a specific reason to do so. In the programs you’re writing at this point, the only lines you should indent are the actions you want to repeat for each item in a for loop. Indenting Unnecessarily After the Loop If you accidentally indent code that should run after a loop has finished, that code will be repeated once for each item in the list. Sometimes this prompts Python to report an error, but often you’ll receive a simple logical error. For example, let’s see what happens when we accidentally indent the line that thanked the magicians as a group for putting on a good show: magicians = ['alice', 'david', 'carolina'] for magician in magicians: print(magician.title() + ", that was a great trick!") print("I can't wait to see your next trick, " + magician.title() + ".\n") u print("Thank you everyone, that was a great magic show!") Because the line at u is indented, it’s printed once for each person in the list, as you can see at v: Alice, that was a great trick! I can't wait to see your next trick, Alice. v Thank you everyone, that was a great magic show! David, that was a great trick! I can't wait to see your next trick, David. v Thank you everyone, that was a great magic show! Carolina, that was a great trick! I can't wait to see your next trick, Carolina. v Thank you everyone, that was a great magic show!

60 Chapter 4 This is another logical error, similar to the one in “Forgetting to Indent Additional Lines” on page 58. Because Python doesn’t know what you’re trying to accomplish with your code, it will run all code that is written in valid syntax. If an action is repeated many times when it should be executed only once, determine whether you just need to unindent the code for that action. Forgetting the Colon The colon at the end of a for statement tells Python to interpret the next line as the start of a loop. magicians = ['alice', 'david', 'carolina'] u for magician in magicians print(magician) If you accidentally forget the colon, as shown at u, you’ll get a syntax error because Python doesn’t know what you’re trying to do. Although this is an easy error to fix, it’s not always an easy error to find. You’d be surprised by the amount of time programmers spend hunting down single- character errors like this. Such errors are difficult to find because we often just see what we expect to see. try It yourse lf 4-1. Pizzas: Think of at least three kinds of your favorite pizza Store these pizza names in a list, and then use a for loop to print the name of each pizza • Modify your for loop to print a sentence using the name of the pizza instead of printing just the name of the pizza For each pizza you should have one line of output containing a simple statement like I like pepperoni pizza • Add a line at the end of your program, outside the for loop, that states how much you like pizza The output should consist of three or more lines about the kinds of pizza you like and then an additional sentence, such as I really love pizza! 4-2. Animals: Think of at least three different animals that have a common char- acteristic Store the names of these animals in a list, and then use a for loop to print out the name of each animal • Modify your program to print a statement about each animal, such as A dog would make a great pet. • Add a line at the end of your program stating what these animals have in common You could print a sentence such as Any of these animals would make a great pet!

Working with Lists 61 making numerical lists Many reasons exist to store a set of numbers. For example, you’ll need to keep track of the positions of each character in a game, and you might want to keep track of a player’s high scores as well. In data visualizations, you’ll almost always work with sets of numbers, such as temperatures, distances, population sizes, or latitude and longitude values, among other types of numerical sets. Lists are ideal for storing sets of numbers, and Python provides a num- ber of tools to help you work efficiently with lists of numbers. Once you understand how to use these tools effectively, your code will work well even when your lists contain millions of items. Using the range() Function Python’s range() function makes it easy to generate a series of numbers. For example, you can use the range() function to print a series of numbers like this: numbers.py for value in range(1,5): print(value) Although this code looks like it should print the numbers from 1 to 5, it doesn’t print the number 5: 1 2 3 4 In this example, range() prints only the numbers 1 through 4. This is another result of the off-by-one behavior you’ll see often in programming languages. The range() function causes Python to start counting at the first value you give it, and it stops when it reaches the second value you provide. Because it stops at that second value, the output never contains the end value, which would have been 5 in this case. To print the numbers from 1 to 5, you would use range(1,6): for value in range(1,6): print(value) This time the output starts at 1 and ends at 5: 1 2 3 4 5

62 Chapter 4 If your output is different than what you expect when you’re using range(), try adjusting your end value by 1. Using range() to Make a List of Numbers If you want to make a list of numbers, you can convert the results of range() directly into a list using the list() function. When you wrap list() around a call to the range() function, the output will be a list of numbers. In the example in the previous section, we simply printed out a series of numbers. We can use list() to convert that same set of numbers into a list: numbers = list(range(1,6)) print(numbers) And this is the result: [1, 2, 3, 4, 5] We can also use the range() function to tell Python to skip numbers in a given range. For example, here’s how we would list the even numbers between 1 and 10: even_numbers.py even_numbers = list(range(2,11,2)) print(even_numbers) In this example, the range() function starts with the value 2 and then adds 2 to that value. It adds 2 repeatedly until it reaches or passes the end value, 11, and produces this result: [2, 4, 6, 8, 10] You can create almost any set of numbers you want to using the range() function. For example, consider how you might make a list of the first 10 square numbers (that is, the square of each integer from 1 through 10). In Python, two asterisks (**) represent exponents. Here’s how you might put the first 10 square numbers into a list: squares.py u squares = [] v for value in range(1,11): w square = value**2 x squares.append(square) y print(squares) We start with an empty list called squares at u. At v, we tell Python to loop through each value from 1 to 10 using the range() function. Inside the loop, the current value is raised to the second power and stored in the

Working with Lists 63 variable square at w. At x, each new value of square is appended to the list squares. Finally, when the loop has finished running, the list of squares is printed at y: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] To write this code more concisely, omit the temporary variable square and append each new value directly to the list: squares = [] for value in range(1,11): u squares.append(value**2) print(squares) The code at u does the same work as the lines at w and x in squares.py. Each value in the loop is raised to the second power and then immediately appended to the list of squares. You can use either of these two approaches when you’re making more complex lists. Sometimes using a temporary variable makes your code eas- ier to read; other times it makes the code unnecessarily long. Focus first on writing code that you understand clearly, which does what you want it to do. Then look for more efficient approaches as you review your code. Simple Statistics with a List of Numbers A few Python functions are specific to lists of numbers. For example, you can easily find the minimum, maximum, and sum of a list of numbers: >>> digits = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] >>> min(digits) 0 >>> max(digits) 9 >>> sum(digits) 45 n o t e The examples in this section use short lists of numbers in order to fit easily on the page. They would work just as well if your list contained a million or more numbers. List Comprehensions The approach described earlier for generating the list squares consisted of using three or four lines of code. A list comprehension allows you to generate this same list in just one line of code. A list comprehension combines the for loop and the creation of new elements into one line, and automatically appends each new element. List comprehensions are not always presented to beginners, but I have included them here because you’ll most likely see them as soon as you start looking at other people’s code.

64 Chapter 4 The following example builds the same list of square numbers you saw earlier but uses a list comprehension: squares.py squares = [value**2 for value in range(1,11)] print(squares) To use this syntax, begin with a descriptive name for the list, such as squares. Next, open a set of square brackets and define the expression for the values you want to store in the new list. In this example the expres- sion is value**2, which raises the value to the second power. Then, write a for loop to generate the numbers you want to feed into the expression, and close the square brackets. The for loop in this example is for value in range(1,11), which feeds the values 1 through 10 into the expression value**2. Notice that no colon is used at the end of the for statement. The result is the same list of square numbers you saw earlier: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] It takes practice to write your own list comprehensions, but you’ll find them worthwhile once you become comfortable creating ordinary lists. When you’re writing three or four lines of code to generate lists and it begins to feel repetitive, consider writing your own list comprehensions. try It yourse lf 4-3. Counting to Twenty: Use a for loop to print the numbers from 1 to 20, inclusive 4-4. One Million: Make a list of the numbers from one to one million, and then use a for loop to print the numbers (If the output is taking too long, stop it by pressing ctrl-C or by closing the output window ) 4-5. Summing a Million: Make a list of the numbers from one to one million, and then use min() and max() to make sure your list actually starts at one and ends at one million Also, use the sum() function to see how quickly Python can add a million numbers 4-6. Odd Numbers: Use the third argument of the range() function to make a list of the odd numbers from 1 to 20 Use a for loop to print each number 4-7. Threes: Make a list of the multiples of 3 from 3 to 30 Use a for loop to print the numbers in your list 4-8. Cubes: A number raised to the third power is called a cube For example, the cube of 2 is written as 2**3 in Python Make a list of the first 10 cubes (that is, the cube of each integer from 1 through 10), and use a for loop to print out the value of each cube 4-9. Cube Comprehension: Use a list comprehension to generate a list of the first 10 cubes

Working with Lists 65 working with Part of a list In Chapter 3 you learned how to access single elements in a list, and in this chapter you’ve been learning how to work through all the elements in a list. You can also work with a specific group of items in a list, which Python calls a slice. Slicing a List To make a slice, you specify the index of the first and last elements you want to work with. As with the range() function, Python stops one item before the second index you specify. To output the first three elements in a list, you would request indices 0 through 3, which would return ele- ments 0, 1, and 2. The following example involves a list of players on a team: players.py players = ['charles', 'martina', 'michael', 'florence', 'eli'] u print(players[0:3]) The code at u prints a slice of this list, which includes just the first three players. The output retains the structure of the list and includes the first three players in the list: ['charles', 'martina', 'michael'] You can generate any subset of a list. For example, if you want the sec- ond, third, and fourth items in a list, you would start the slice at index 1 and end at index 4: players = ['charles', 'martina', 'michael', 'florence', 'eli'] print(players[1:4]) This time the slice starts with 'martina' and ends with 'florence': ['martina', 'michael', 'florence'] If you omit the first index in a slice, Python automatically starts your slice at the beginning of the list: players = ['charles', 'martina', 'michael', 'florence', 'eli'] print(players[:4]) Without a starting index, Python starts at the beginning of the list: ['charles', 'martina', 'michael', 'florence']

66 Chapter 4 A similar syntax works if you want a slice that includes the end of a list. For example, if you want all items from the third item through the last item, you can start with index 2 and omit the second index: players = ['charles', 'martina', 'michael', 'florence', 'eli'] print(players[2:]) Python returns all items from the third item through the end of the list: ['michael', 'florence', 'eli'] This syntax allows you to output all of the elements from any point in your list to the end regardless of the length of the list. Recall that a nega- tive index returns an element a certain distance from the end of a list; therefore, you can output any slice from the end of a list. For example, if we want to output the last three players on the roster, we can use the slice players[-3:]: players = ['charles', 'martina', 'michael', 'florence', 'eli'] print(players[-3:]) This prints the names of the last three players and would continue to work as the list of players changes in size. Looping Through a Slice You can use a slice in a for loop if you want to loop through a subset of the elements in a list. In the next example we loop through the first three players and print their names as part of a simple roster: players = ['charles', 'martina', 'michael', 'florence', 'eli'] print("Here are the first three players on my team:") u for player in players[:3]: print(player.title()) Instead of looping through the entire list of players at u, Python loops through only the first three names: Here are the first three players on my team: Charles Martina Michael Slices are very useful in a number of situations. For instance, when you’re creating a game, you could add a player’s final score to a list every time that player finishes playing. You could then get a player’s top three scores by sort- ing the list in decreasing order and taking a slice that includes just the first three scores. When you’re working with data, you can use slices to process

Working with Lists 67 your data in chunks of a specific size. Or, when you’re building a web appli- cation, you could use slices to display information in a series of pages with an appropriate amount of information on each page. Copying a List Often, you’ll want to start with an existing list and make an entirely new list based on the first one. Let’s explore how copying a list works and examine one situation in which copying a list is useful. To copy a list, you can make a slice that includes the entire original list by omitting the first index and the second index ([:]). This tells Python to make a slice that starts at the first item and ends with the last item, produc- ing a copy of the entire list. For example, imagine we have a list of our favorite foods and want to make a separate list of foods that a friend likes. This friend likes everything in our list so far, so we can create their list by copying ours: foods.py u my_foods = ['pizza', 'falafel', 'carrot cake'] v friend_foods = my_foods[:] print("My favorite foods are:") print(my_foods) print("\nMy friend's favorite foods are:") print(friend_foods) At u we make a list of the foods we like called my_foods. At v we make a new list called friend_foods. We make a copy of my_foods by asking for a slice of my_foods without specifying any indices and store the copy in friend_foods. When we print each list, we see that they both contain the same foods: My favorite foods are: ['pizza', 'falafel', 'carrot cake'] My friend's favorite foods are: ['pizza', 'falafel', 'carrot cake'] To prove that we actually have two separate lists, we’ll add a new food to each list and show that each list keeps track of the appropriate person’s favorite foods: my_foods = ['pizza', 'falafel', 'carrot cake'] u friend_foods = my_foods[:] v my_foods.append('cannoli') w friend_foods.append('ice cream') print("My favorite foods are:") print(my_foods)

68 Chapter 4 print("\nMy friend's favorite foods are:") print(friend_foods) At u we copy the original items in my_foods to the new list friend_foods, as we did in the previous example. Next, we add a new food to each list: at v we add 'cannoli' to my_foods, and at w we add 'ice cream' to friend_foods. We then print the two lists to see whether each of these foods is in the appropriate list. My favorite foods are: x ['pizza', 'falafel', 'carrot cake', 'cannoli'] My friend's favorite foods are: y ['pizza', 'falafel', 'carrot cake', 'ice cream'] The output at x shows that 'cannoli' now appears in our list of favorite foods but 'ice cream' doesn’t. At y we can see that 'ice cream' now appears in our friend’s list but 'cannoli' doesn’t. If we had simply set friend_foods equal to my_foods, we would not produce two separate lists. For example, here’s what happens when you try to copy a list without using a slice: my_foods = ['pizza', 'falafel', 'carrot cake'] # This doesn't work: u friend_foods = my_foods my_foods.append('cannoli') friend_foods.append('ice cream') print("My favorite foods are:") print(my_foods) print("\nMy friend's favorite foods are:") print(friend_foods) Instead of storing a copy of my_foods in friend_foods at u, we set friend_foods equal to my_foods. This syntax actually tells Python to con- nect the new variable friend_foods to the list that is already contained in my_foods, so now both variables point to the same list. As a result, when we add 'cannoli' to my_foods, it will also appear in friend_foods. Likewise 'ice cream' will appear in both lists, even though it appears to be added only to friend_foods. The output shows that both lists are the same now, which is not what we wanted: My favorite foods are: ['pizza', 'falafel', 'carrot cake', 'cannoli', 'ice cream'] My friend's favorite foods are: ['pizza', 'falafel', 'carrot cake', 'cannoli', 'ice cream']

Working with Lists 69 n o t e Don’t worry about the details in this example for now. Basically, if you’re trying to work with a copy of a list and you see unexpected behavior, make sure you are copying the list using a slice, as we did in the first example. try It yourse lf 4-10. Slices: Using one of the programs you wrote in this chapter, add several lines to the end of the program that do the following: • Print the message, The first three items in the list are: Then use a slice to print the first three items from that program’s list • Print the message, Three items from the middle of the list are: Use a slice to print three items from the middle of the list • Print the message, The last three items in the list are: Use a slice to print the last three items in the list 4-11. My Pizzas, Your Pizzas: Start with your program from Exercise 4-1 (page 60) Make a copy of the list of pizzas, and call it friend_pizzas Then, do the following: • Add a new pizza to the original list • Add a different pizza to the list friend_pizzas • Prove that you have two separate lists Print the message, My favorite pizzas are:, and then use a for loop to print the first list Print the message, My friend’s favorite pizzas are:, and then use a for loop to print the sec- ond list Make sure each new pizza is stored in the appropriate list 4-12. More Loops: All versions of foods.py in this section have avoided using for loops when printing to save space Choose a version of foods.py, and write two for loops to print each list of foods tuples Lists work well for storing sets of items that can change throughout the life of a program. The ability to modify lists is particularly important when you’re working with a list of users on a website or a list of characters in a game. However, sometimes you’ll want to create a list of items that cannot change. Tuples allow you to do just that. Python refers to values that cannot change as immutable, and an immutable list is called a tuple. Defining a Tuple A tuple looks just like a list except you use parentheses instead of square brackets. Once you define a tuple, you can access individual elements by using each item’s index, just as you would for a list.

70 Chapter 4 For example, if we have a rectangle that should always be a certain size, we can ensure that its size doesn’t change by putting the dimensions into a tuple: dimensions.py u dimensions = (200, 50) v print(dimensions[0]) print(dimensions[1]) We define the tuple dimensions at u, using parentheses instead of square brackets. At v we print each element in the tuple individually, using the same syntax we’ve been using to access elements in a list: 200 50 Let’s see what happens if we try to change one of the items in the tuple dimensions: dimensions = (200, 50) u dimensions[0] = 250 The code at u tries to change the value of the first dimension, but Python returns a type error. Basically, because we’re trying to alter a tuple, which can’t be done to that type of object, Python tells us we can’t assign a new value to an item in a tuple: Traceback (most recent call last): File "dimensions.py", line 3, in <module> dimensions[0] = 250 TypeError: 'tuple' object does not support item assignment This is beneficial because we want Python to raise an error when a line of code tries to change the dimensions of the rectangle. Looping Through All Values in a Tuple You can loop over all the values in a tuple using a for loop, just as you did with a list: dimensions = (200, 50) for dimension in dimensions: print(dimension) Python returns all the elements in the tuple, just as it would for a list: 200 50

Working with Lists 71 Writing over a Tuple Although you can’t modify a tuple, you can assign a new value to a variable that holds a tuple. So if we wanted to change our dimensions, we could redefine the entire tuple: u dimensions = (200, 50) print("Original dimensions:") for dimension in dimensions: print(dimension) v dimensions = (400, 100) w print("\nModified dimensions:") for dimension in dimensions: print(dimension) The block at u defines the original tuple and prints the initial dimen- sions. At v, we store a new tuple in the variable dimensions. We then print the new dimensions at w. Python doesn’t raise any errors this time, because overwriting a variable is valid: Original dimensions: 200 50 Modified dimensions: 400 100 When compared with lists, tuples are simple data structures. Use them when you want to store a set of values that should not be changed through- out the life of a program. try It yourse lf 4-13. Buffet: A buffet-style restaurant offers only five basic foods Think of five simple foods, and store them in a tuple • Use a for loop to print each food the restaurant offers • Try to modify one of the items, and make sure that Python rejects the change • The restaurant changes its menu, replacing two of the items with different foods Add a block of code that rewrites the tuple, and then use a for loop to print each of the items on the revised menu

72 Chapter 4 styling your Code Now that you’re writing longer programs, ideas about how to style your code are worthwhile to know. Take the time to make your code as easy as possible to read. Writing easy-to-read code helps you keep track of what your pro- grams are doing and helps others understand your code as well. Python programmers have agreed on a number of styling conven- tions to ensure that everyone’s code is structured in roughly the same way. Once you’ve learned to write clean Python code, you should be able to understand the overall structure of anyone else’s Python code, as long as they follow the same guidelines. If you’re hoping to become a professional programmer at some point, you should begin following these guidelines as soon as possible to develop good habits. The Style Guide When someone wants to make a change to the Python language, they write a Python Enhancement Proposal (PEP). One of the oldest PEPs is PEP 8, which instructs Python programmers on how to style their code. PEP 8 is fairly lengthy, but much of it relates to more complex coding structures than what you’ve seen so far. The Python style guide was written with the understanding that code is read more often than it is written. You’ll write your code once and then start reading it as you begin debugging. When you add features to a pro- gram, you’ll spend more time reading your code. When you share your code with other programmers, they’ll read your code as well. Given the choice between writing code that’s easier to write or code that’s easier to read, Python programmers will almost always encourage you to write code that’s easier to read. The following guidelines will help you write clear code from the start. Indentation PEP 8 recommends that you use four spaces per indentation level. Using four spaces improves readability while leaving room for multiple levels of indentation on each line. In a word processing document, people often use tabs rather than spaces to indent. This works well for word processing documents, but the Python interpreter gets confused when tabs are mixed with spaces. Every text editor provides a setting that lets you use the tab key but then converts each tab to a set number of spaces. You should definitely use your tab key, but also make sure your editor is set to insert spaces rather than tabs into your document. Mixing tabs and spaces in your file can cause problems that are very difficult to diagnose. If you think you have a mix of tabs and spaces, you can convert all tabs in a file to spaces in most editors.

Working with Lists 73 Line Length Many Python programmers recommend that each line should be less than 80 characters. Historically, this guideline developed because most com- puters could fit only 79 characters on a single line in a terminal window. Currently, people can fit much longer lines on their screens, but other rea- sons exist to adhere to the 79-character standard line length. Professional programmers often have several files open on the same screen, and using the standard line length allows them to see entire lines in two or three files that are open side by side onscreen. PEP 8 also recommends that you limit all of your comments to 72 characters per line, because some of the tools that generate automatic documentation for larger projects add formatting characters at the beginning of each commented line. The PEP 8 guidelines for line length are not set in stone, and some teams prefer a 99-character limit. Don’t worry too much about line length in your code as you’re learning, but be aware that people who are work- ing collaboratively almost always follow the PEP 8 guidelines. Most editors allow you to set up a visual cue, usually a vertical line on your screen, that shows you where these limits are. n o t e Appendix B shows you how to configure your text editor so it always inserts four spaces each time you press the tab key and shows a vertical guideline to help you follow the 79-character limit. Blank Lines To group parts of your program visually, use blank lines. You should use blank lines to organize your files, but don’t do so excessively. By following the examples provided in this book, you should strike the right balance. For example, if you have five lines of code that build a list, and then another three lines that do something with that list, it’s appropriate to place a blank line between the two sections. However, you should not place three or four blank lines between the two sections. Blank lines won’t affect how your code runs, but they will affect the readability of your code. The Python interpreter uses horizontal inden- tation to interpret the meaning of your code, but it disregards vertical spacing. Other Style Guidelines PEP 8 has many additional styling recommendations, but most of the guide- lines refer to more complex programs than what you’re writing at this point. As you learn more complex Python structures, I’ll share the relevant parts of the PEP 8 guidelines.

74 Chapter 4 try It yourse lf 4-14. PEP 8: Look through the original PEP 8 style guide at https://python.org/ dev/peps/pep-0008/ You won’t use much of it now, but it might be interesting to skim through it 4-15. Code Review: Choose three of the programs you’ve written in this chapter and modify each one to comply with PEP 8: • Use four spaces for each indentation level Set your text editor to insert four spaces every time you press tab, if you haven’t already done so (see Appendix B for instructions on how to do this) • Use less than 80 characters on each line, and set your editor to show a vertical guideline at the 80th character position • Don’t use blank lines excessively in your program files summary In this chapter you learned how to work efficiently with the elements in a list. You learned how to work through a list using a for loop, how Python uses indentation to structure a program, and how to avoid some common indentation errors. You learned to make simple numerical lists, as well as a few operations you can perform on numerical lists. You learned how to slice a list to work with a subset of items and how to copy lists properly using a slice. You also learned about tuples, which provide a degree of protection to a set of values that shouldn’t change, and how to style your increasingly complex code to make it easy to read. In Chapter 5, you’ll learn to respond appropriately to different condi- tions by using if statements. You’ll learn to string together relatively com- plex sets of conditional tests to respond appropriately to exactly the kind of situation or information you’re looking for. You’ll also learn to use if statements while looping through a list to take specific actions with selected elements from a list.

5I f s t a t e m e n t s Programming often involves examining a set of conditions and deciding which action to take based on those conditions. Python’s if statement allows you to examine the current state of a program and respond appropriately to that state. In this chapter you’ll learn to write conditional tests, which allow you to check any condition of interest. You’ll learn to write simple if statements, and you’ll learn how to create a more complex series of if statements to identify when the exact conditions you want are present. You’ll then apply this concept to lists, so you’ll be able to write a for loop that handles most items in a list one way but handles certain items with specific values in a different way.

76 Chapter 5 a simple example The following short example shows how if tests let you respond to special situations correctly. Imagine you have a list of cars and you want to print out the name of each car. Car names are proper names, so the names of most cars should be printed in title case. However, the value 'bmw' should be printed in all uppercase. The following code loops through a list of car names and looks for the value 'bmw'. Whenever the value is 'bmw', it’s printed in uppercase instead of title case: cars.py cars = ['audi', 'bmw', 'subaru', 'toyota'] for car in cars: u if car == 'bmw': print(car.upper()) else: print(car.title()) The loop in this example first checks if the current value of car is 'bmw' u. If it is, the value is printed in uppercase. If the value of car is anything other than 'bmw', it’s printed in title case: Audi BMW Subaru Toyota This example combines a number of the concepts you’ll learn about in this chapter. Let’s begin by looking at the kinds of tests you can use to examine the conditions in your program. Conditional tests At the heart of every if statement is an expression that can be evaluated as True or False and is called a conditional test. Python uses the values True and False to decide whether the code in an if statement should be executed. If a conditional test evaluates to True, Python executes the code following the if statement. If the test evaluates to False, Python ignores the code following the if statement. Checking for Equality Most conditional tests compare the current value of a variable to a specific value of interest. The simplest conditional test checks whether the value of a variable is equal to the value of interest: u >>> car = 'bmw' v >>> car == 'bmw' True

if Statements 77 The line at u sets the value of car to 'bmw' using a single equal sign, as you’ve seen many times already. The line at v checks whether the value of car is 'bmw' using a double equal sign (==). This equality operator returns True if the values on the left and right side of the operator match, and False if they don’t match. The values in this example match, so Python returns True. When the value of car is anything other than 'bmw', this test returns False: u >>> car = 'audi' v >>> car == 'bmw' False A single equal sign is really a statement; you might read the code at u as “Set the value of car equal to 'audi'.” On the other hand, a double equal sign, like the one at v, asks a question: “Is the value of car equal to 'bmw'?” Most programming languages use equal signs in this way. Ignoring Case When Checking for Equality Testing for equality is case sensitive in Python. For example, two values with different capitalization are not considered equal: >>> car = 'Audi' >>> car == 'audi' False If case matters, this behavior is advantageous. But if case doesn’t matter and instead you just want to test the value of a variable, you can convert the variable’s value to lowercase before doing the comparison: >>> car = 'Audi' >>> car.lower() == 'audi' True This test would return True no matter how the value 'Audi' is formatted because the test is now case insensitive. The lower() function doesn’t change the value that was originally stored in car, so you can do this kind of com- parison without affecting the original variable: u >>> car = 'Audi' v >>> car.lower() == 'audi' True w >>> car 'Audi' At u we store the capitalized string 'Audi' in the variable car. At v we convert the value of car to lowercase and compare the lowercase value

78 Chapter 5 to the string 'audi'. The two strings match, so Python returns True. At w we can see that the value stored in car has not been affected by the condi- tional test. Websites enforce certain rules for the data that users enter in a manner similar to this. For example, a site might use a conditional test like this to ensure that every user has a truly unique username, not just a variation on the capitalization of another person’s username. When some- one submits a new username, that new username is converted to lowercase and compared to the lowercase versions of all existing usernames. During this check, a username like 'John' will be rejected if any variation of 'john' is already in use. Checking for Inequality When you want to determine whether two values are not equal, you can combine an exclamation point and an equal sign (!=). The exclamation point represents not, as it does in many programming languages. Let’s use another if statement to examine how to use the inequality operator. We’ll store a requested pizza topping in a variable and then print a message if the person did not order anchovies: toppings.py requested_topping = 'mushrooms' u if requested_topping != 'anchovies': print("Hold the anchovies!") The line at u compares the value of requested_topping to the value 'anchovies'. If these two values do not match, Python returns True and exe- cutes the code following the if statement. If the two values match, Python returns False and does not run the code following the if statement. Because the value of requested_topping is not 'anchovies', the print state- ment is executed: Hold the anchovies! Most of the conditional expressions you write will test for equality, but sometimes you’ll find it more efficient to test for inequality. Numerical Comparisons Testing numerical values is pretty straightforward. For example, the follow- ing code checks whether a person is 18 years old: >>> age = 18 >>> age == 18 True

if Statements 79 You can also test to see if two numbers are not equal. For example, the following code prints a message if the given answer is not correct: magic_ answer = 17 number.py u if answer != 42: print("That is not the correct answer. Please try again!") The conditional test at u passes, because the value of answer (17) is not equal to 42. Because the test passes, the indented code block is executed: That is not the correct answer. Please try again! You can include various mathematical comparisons in your conditional statements as well, such as less than, less than or equal to, greater than, and greater than or equal to: >>> age = 19 >>> age < 21 True >>> age <= 21 True >>> age > 21 False >>> age >= 21 False Each mathematical comparison can be used as part of an if statement, which can help you detect the exact conditions of interest. Checking Multiple Conditions You may want to check multiple conditions at the same time. For example, sometimes you might need two conditions to be True to take an action. Other times you might be satisfied with just one condition being True. The keywords and and or can help you in these situations. Using and to Check Multiple Conditions To check whether two conditions are both True simultaneously, use the key- word and to combine the two conditional tests; if each test passes, the over- all expression evaluates to True. If either test fails or if both tests fail, the expression evaluates to False. For example, you can check whether two people are both over 21 using the following test: u >>> age_0 = 22 >>> age_1 = 18 v >>> age_0 >= 21 and age_1 >= 21 False

80 Chapter 5 w >>> age_1 = 22 >>> age_0 >= 21 and age_1 >= 21 True At u we define two ages, age_0 and age_1. At v we check whether both ages are 21 or older. The test on the left passes, but the test on the right fails, so the overall conditional expression evaluates to False. At w we change age_1 to 22. The value of age_1 is now greater than 21, so both individual tests pass, causing the overall conditional expression to evaluate as True. To improve readability, you can use parentheses around the individual tests, but they are not required. If you use parentheses, your test would look like this: (age_0 >= 21) and (age_1 >= 21) Using or to Check Multiple Conditions The keyword or allows you to check multiple conditions as well, but it passes when either or both of the individual tests pass. An or expression fails only when both individual tests fail. Let’s consider two ages again, but this time we’ll look for only one per- son to be over 21: u >>> age_0 = 22 >>> age_1 = 18 v >>> age_0 >= 21 or age_1 >= 21 True w >>> age_0 = 18 >>> age_0 >= 21 or age_1 >= 21 False We start with two age variables again at u. Because the test for age_0 at v passes, the overall expression evaluates to True. We then lower age_0 to 18. In the test at w, both tests now fail and the overall expression evaluates to False. Checking Whether a Value Is in a List Sometimes it’s important to check whether a list contains a certain value before taking an action. For example, you might want to check whether a new username already exists in a list of current usernames before complet- ing someone’s registration on a website. In a mapping project, you might want to check whether a submitted location already exists in a list of known locations. To find out whether a particular value is already in a list, use the key- word in. Let’s consider some code you might write for a pizzeria. We’ll make a list of toppings a customer has requested for a pizza and then check whether certain toppings are in the list.

if Statements 81 >>> requested_toppings = ['mushrooms', 'onions', 'pineapple'] u >>> 'mushrooms' in requested_toppings True v >>> 'pepperoni' in requested_toppings False At u and v, the keyword in tells Python to check for the existence of 'mushrooms' and 'pepperoni' in the list requested_toppings. This technique is quite powerful because you can create a list of essential values, and then easily check whether the value you’re testing matches one of the values in the list. Checking Whether a Value Is Not in a List Other times, it’s important to know if a value does not appear in a list. You can use the keyword not in this situation. For example, consider a list of users who are banned from commenting in a forum. You can check whether a user has been banned before allowing that person to submit a comment: banned_ banned_users = ['andrew', 'carolina', 'david'] users.py user = 'marie' u if user not in banned_users: print(user.title() + ", you can post a response if you wish.") The line at u reads quite clearly. If the value of user is not in the list banned_users, Python returns True and executes the indented line. The user 'marie' is not in the list banned_users, so she sees a message inviting her to post a response: Marie, you can post a response if you wish. Boolean Expressions As you learn more about programming, you’ll hear the term Boolean expression at some point. A Boolean expression is just another name for a conditional test. A Boolean value is either True or False, just like the value of a conditional expression after it has been evaluated. Boolean values are often used to keep track of certain conditions, such as whether a game is running or whether a user can edit certain content on a website: game_active = True can_edit = False Boolean values provide an efficient way to track the state of a program or a particular condition that is important in your program.

82 Chapter 5 try It yourse lf 5-1. Conditional Tests: Write a series of conditional tests Print a statement describing each test and your prediction for the results of each test Your code should look something like this: car = 'subaru' print("Is car == 'subaru'? I predict True.") print(car == 'subaru') print("\nIs car == 'audi'? I predict False.") print(car == 'audi') • Look closely at your results, and make sure you understand why each line evaluates to True or False • Create at least 10 tests Have at least 5 tests evaluate to True and another 5 tests evaluate to False 5-2. More Conditional Tests: You don’t have to limit the number of tests you create to 10 If you want to try more comparisons, write more tests and add them to conditional_tests.py Have at least one True and one False result for each of the following: • Tests for equality and inequality with strings • Tests using the lower() function • Numerical tests involving equality and inequality, greater than and less than, greater than or equal to, and less than or equal to • Tests using the and keyword and the or keyword • Test whether an item is in a list • Test whether an item is not in a list if statements When you understand conditional tests, you can start writing if statements. Several different kinds of if statements exist, and your choice of which to use depends on the number of conditions you need to test. You saw several examples of if statements in the discussion about conditional tests, but now let’s dig deeper into the topic. Simple if Statements The simplest kind of if statement has one test and one action: if conditional_test: do something

if Statements 83 You can put any conditional test in the first line and just about any action in the indented block following the test. If the conditional test evaluates to True, Python executes the code following the if statement. If the test evaluates to False, Python ignores the code following the if statement. Let’s say we have a variable representing a person’s age, and we want to know if that person is old enough to vote. The following code tests whether the person can vote: voting.py age = 19 u if age >= 18: v print("You are old enough to vote!") At u Python checks to see whether the value in age is greater than or equal to 18. It is, so Python executes the indented print statement at v: You are old enough to vote! Indentation plays the same role in if statements as it did in for loops. All indented lines after an if statement will be executed if the test passes, and the entire block of indented lines will be ignored if the test does not pass. You can have as many lines of code as you want in the block follow- ing the if statement. Let’s add another line of output if the person is old enough to vote, asking if the individual has registered to vote yet: age = 19 if age >= 18: print("You are old enough to vote!") print("Have you registered to vote yet?") The conditional test passes, and both print statements are indented, so both lines are printed: You are old enough to vote! Have you registered to vote yet? If the value of age is less than 18, this program would produce no output. if-else Statements Often, you’ll want to take one action when a conditional test passes and a dif- ferent action in all other cases. Python’s if-else syntax makes this possible. An if-else block is similar to a simple if statement, but the else statement allows you to define an action or set of actions that are executed when the conditional test fails.

84 Chapter 5 We’ll display the same message we had previously if the person is old enough to vote, but this time we’ll add a message for anyone who is not old enough to vote: age = 17 u if age >= 18: print("You are old enough to vote!") print("Have you registered to vote yet?") v else: print("Sorry, you are too young to vote.") print("Please register to vote as soon as you turn 18!") If the conditional test at u passes, the first block of indented print statements is executed. If the test evaluates to False, the else block at v is executed. Because age is less than 18 this time, the conditional test fails and the code in the else block is executed: Sorry, you are too young to vote. Please register to vote as soon as you turn 18! This code works because it has only two possible situations to evaluate: a person is either old enough to vote or not old enough to vote. The if-else structure works well in situations in which you want Python to always execute one of two possible actions. In a simple if-else chain like this, one of the two actions will always be executed. The if-elif-else Chain Often, you’ll need to test more than two possible situations, and to evaluate these you can use Python’s if-elif-else syntax. Python executes only one block in an if-elif-else chain. It runs each conditional test in order until one passes. When a test passes, the code following that test is executed and Python skips the rest of the tests. Many real-world situations involve more than two possible conditions. For example, consider an amusement park that charges different rates for different age groups: • Admission for anyone under age 4 is free. • Admission for anyone between the ages of 4 and 18 is $5. • Admission for anyone age 18 or older is $10. How can we use an if statement to determine a person’s admission rate? The following code tests for the age group of a person and then prints an admission price message: amusement_ age = 12 park.py u if age < 4: print("Your admission cost is $0.")

if Statements 85 v elif age < 18: print("Your admission cost is $5.") w else: print("Your admission cost is $10.") The if test at u tests whether a person is under 4 years old. If the test passes, an appropriate message is printed and Python skips the rest of the tests. The elif line at v is really another if test, which runs only if the pre- vious test failed. At this point in the chain, we know the person is at least 4 years old because the first test failed. If the person is less than 18, an appropriate message is printed and Python skips the else block. If both the if and elif tests fail, Python runs the code in the else block at w. In this example the test at u evaluates to False, so its code block is not executed. However, the second test evaluates to True (12 is less than 18) so its code is executed. The output is one sentence, informing the user of the admission cost: Your admission cost is $5. Any age greater than 17 would cause the first two tests to fail. In these situations, the else block would be executed and the admission price would be $10. Rather than printing the admission price within the if-elif-else block, it would be more concise to set just the price inside the if-elif-else chain and then have a simple print statement that runs after the chain has been evaluated: age = 12 if age < 4: u price = 0 elif age < 18: v price = 5 else: w price = 10 x print("Your admission cost is $" + str(price) + ".") The lines at u, v, and w set the value of price according to the person’s age, as in the previous example. After the price is set by the if-elif-else chain, a separate unindented print statement x uses this value to display a mes- sage reporting the person’s admission price. This code produces the same output as the previous example, but the purpose of the if-elif-else chain is narrower. Instead of determining a price and displaying a message, it simply determines the admission price. In addition to being more efficient, this revised code is easier to modify than the original approach. To change the text of the output message, you would need to change only one print statement rather than three separate print statements.

86 Chapter 5 Using Multiple elif Blocks You can use as many elif blocks in your code as you like. For example, if the amusement park were to implement a discount for seniors, you could add one more conditional test to the code to determine whether someone quali- fied for the senior discount. Let’s say that anyone 65 or older pays half the regular admission, or $5: age = 12 if age < 4: price = 0 elif age < 18: price = 5 u elif age < 65: price = 10 v else: price = 5 print("Your admission cost is $" + str(price) + ".") Most of this code is unchanged. The second elif block at u now checks to make sure a person is less than age 65 before assigning them the full admission rate of $10. Notice that the value assigned in the else block at v needs to be changed to $5, because the only ages that make it to this block are people 65 or older. Omitting the else Block Python does not require an else block at the end of an if-elif chain. Some- times an else block is useful; sometimes it is clearer to use an additional elif statement that catches the specific condition of interest: age = 12 if age < 4: price = 0 elif age < 18: price = 5 elif age < 65: price = 10 u elif age >= 65: price = 5 print("Your admission cost is $" + str(price) + ".") The extra elif block at u assigns a price of $5 when the person is 65 or older, which is a bit clearer than the general else block. With this change, every block of code must pass a specific test in order to be executed.

if Statements 87 The else block is a catchall statement. It matches any condition that wasn’t matched by a specific if or elif test, and that can sometimes include invalid or even malicious data. If you have a specific final condition you are testing for, consider using a final elif block and omit the else block. As a result, you’ll gain extra confidence that your code will run only under the correct conditions. Testing Multiple Conditions The if-elif-else chain is powerful, but it’s only appropriate to use when you just need one test to pass. As soon as Python finds one test that passes, it skips the rest of the tests. This behavior is beneficial, because it’s efficient and allows you to test for one specific condition. However, sometimes it’s important to check all of the conditions of interest. In this case, you should use a series of simple if statements with no elif or else blocks. This technique makes sense when more than one condi- tion could be True, and you want to act on every condition that is True. Let’s reconsider the pizzeria example. If someone requests a two-topping pizza, you’ll need to be sure to include both toppings on their pizza: toppings.py u requested_toppings = ['mushrooms', 'extra cheese'] v if 'mushrooms' in requested_toppings: print("Adding mushrooms.") w if 'pepperoni' in requested_toppings: print("Adding pepperoni.") x if 'extra cheese' in requested_toppings: print("Adding extra cheese.") print("\nFinished making your pizza!") We start at u with a list containing the requested toppings. The if statement at v checks to see whether the person requested mushrooms on their pizza. If so, a message is printed confirming that topping. The test for pepperoni at w is another simple if statement, not an elif or else statement, so this test is run regardless of whether the previous test passed or not. The code at x checks whether extra cheese was requested regard- less of the results from the first two tests. These three independent tests are executed every time this program is run. Because every condition in this example is evaluated, both mushrooms and extra cheese are added to the pizza: Adding mushrooms. Adding extra cheese. Finished making your pizza!

88 Chapter 5 This code would not work properly if we used an if-elif-else block, because the code would stop running after only one test passes. Here’s what that would look like: requested_toppings = ['mushrooms', 'extra cheese'] if 'mushrooms' in requested_toppings: print("Adding mushrooms.") elif 'pepperoni' in requested_toppings: print("Adding pepperoni.") elif 'extra cheese' in requested_toppings: print("Adding extra cheese.") print("\nFinished making your pizza!") The test for 'mushrooms' is the first test to pass, so mushrooms are added to the pizza. However, the values 'extra cheese' and 'pepperoni' are never checked, because Python doesn’t run any tests beyond the first test that passes in an if-elif-else chain. The customer’s first topping will be added, but all of their other toppings will be missed: Adding mushrooms. Finished making your pizza! In summary, if you want only one block of code to run, use an if-elif- else chain. If more than one block of code needs to run, use a series of independent if statements. try It yourse lf 5-3. Alien Colors #1: Imagine an alien was just shot down in a game Create a variable called alien_color and assign it a value of 'green', 'yellow', or 'red' • Write an if statement to test whether the alien’s color is green If it is, print a message that the player just earned 5 points • Write one version of this program that passes the if test and another that fails (The version that fails will have no output ) 5-4. Alien Colors #2: Choose a color for an alien as you did in Exercise 5-3, and write an if-else chain • If the alien’s color is green, print a statement that the player just earned 5 points for shooting the alien • If the alien’s color isn’t green, print a statement that the player just earned 10 points • Write one version of this program that runs the if block and another that runs the else block

if Statements 89 5-5. Alien Colors #3: Turn your if-else chain from Exercise 5-4 into an if-elif- else chain • If the alien is green, print a message that the player earned 5 points • If the alien is yellow, print a message that the player earned 10 points • If the alien is red, print a message that the player earned 15 points • Write three versions of this program, making sure each message is printed for the appropriate color alien 5-6. Stages of Life: Write an if-elif-else chain that determines a person’s stage of life Set a value for the variable age, and then: • If the person is less than 2 years old, print a message that the person is a baby • If the person is at least 2 years old but less than 4, print a message that the person is a toddler • If the person is at least 4 years old but less than 13, print a message that the person is a kid • If the person is at least 13 years old but less than 20, print a message that the person is a teenager • If the person is at least 20 years old but less than 65, print a message that the person is an adult • If the person is age 65 or older, print a message that the person is an elder 5-7. Favorite Fruit: Make a list of your favorite fruits, and then write a series of independent if statements that check for certain fruits in your list • Make a list of your three favorite fruits and call it favorite_fruits • Write five if statements Each should check whether a certain kind of fruit is in your list If the fruit is in your list, the if block should print a statement, such as You really like bananas! using if statements with lists You can do some interesting work when you combine lists and if state- ments. You can watch for special values that need to be treated differently than other values in the list. You can manage changing conditions effi- ciently, such as the availability of certain items in a restaurant throughout a shift. You can also begin to prove that your code works as you expect it to in all possible situations.

90 Chapter 5 Checking for Special Items This chapter began with a simple example that showed how to handle a spe- cial value like 'bmw', which needed to be printed in a different format than other values in the list. Now that you have a basic understanding of condi- tional tests and if statements, let’s take a closer look at how you can watch for special values in a list and handle those values appropriately. Let’s continue with the pizzeria example. The pizzeria displays a message whenever a topping is added to your pizza, as it’s being made. The code for this action can be written very efficiently by making a list of toppings the customer has requested and using a loop to announce each topping as it’s added to the pizza: toppings.py requested_toppings = ['mushrooms', 'green peppers', 'extra cheese'] for requested_topping in requested_toppings: print("Adding " + requested_topping + ".") print("\nFinished making your pizza!") The output is straightforward because this code is just a simple for loop: Adding mushrooms. Adding green peppers. Adding extra cheese. Finished making your pizza! But what if the pizzeria runs out of green peppers? An if statement inside the for loop can handle this situation appropriately: requested_toppings = ['mushrooms', 'green peppers', 'extra cheese'] for requested_topping in requested_toppings: u if requested_topping == 'green peppers': print("Sorry, we are out of green peppers right now.") v else: print("Adding " + requested_topping + ".") print("\nFinished making your pizza!") This time we check each requested item before adding it to the pizza. The code at u checks to see if the person requested green peppers. If so, we display a message informing them why they can’t have green peppers. The else block at v ensures that all other toppings will be added to the pizza.

if Statements 91 The output shows that each requested topping is handled appropriately. Adding mushrooms. Sorry, we are out of green peppers right now. Adding extra cheese. Finished making your pizza! Checking That a List Is Not Empty We’ve made a simple assumption about every list we’ve worked with so far; we’ve assumed that each list has at least one item in it. Soon we’ll let users provide the information that’s stored in a list, so we won’t be able to assume that a list has any items in it each time a loop is run. In this situation, it’s useful to check whether a list is empty before running a for loop. As an example, let’s check whether the list of requested toppings is empty before building the pizza. If the list is empty, we’ll prompt the user and make sure they want a plain pizza. If the list is not empty, we’ll build the pizza just as we did in the previous examples: u requested_toppings = [] v if requested_toppings: for requested_topping in requested_toppings: print("Adding " + requested_topping + ".") print("\nFinished making your pizza!") w else: print("Are you sure you want a plain pizza?") This time we start out with an empty list of requested toppings at u. Instead of jumping right into a for loop, we do a quick check at v. When the name of a list is used in an if statement, Python returns True if the list con- tains at least one item; an empty list evaluates to False. If requested_toppings passes the conditional test, we run the same for loop we used in the previous example. If the conditional test fails, we print a message asking the customer if they really want a plain pizza with no toppings w. The list is empty in this case, so the output asks if the user really wants a plain pizza: Are you sure you want a plain pizza? If the list is not empty, the output will show each requested topping being added to the pizza.

92 Chapter 5 Using Multiple Lists People will ask for just about anything, especially when it comes to pizza toppings. What if a customer actually wants french fries on their pizza? You can use lists and if statements to make sure your input makes sense before you act on it. Let’s watch out for unusual topping requests before we build a pizza. The following example defines two lists. The first is a list of available top- pings at the pizzeria, and the second is the list of toppings that the user has requested. This time, each item in requested_toppings is checked against the list of available toppings before it’s added to the pizza: u available_toppings = ['mushrooms', 'olives', 'green peppers', 'pepperoni', 'pineapple', 'extra cheese'] v requested_toppings = ['mushrooms', 'french fries', 'extra cheese'] w for requested_topping in requested_toppings: x if requested_topping in available_toppings: print("Adding " + requested_topping + ".") y else: print("Sorry, we don't have " + requested_topping + ".") print("\nFinished making your pizza!") At u we define a list of available toppings at this pizzeria. Note that this could be a tuple if the pizzeria has a stable selection of toppings. At v, we make a list of toppings that a customer has requested. Note the unusual request, 'french fries'. At w we loop through the list of requested toppings. Inside the loop, we first check to see if each requested topping is actually in the list of available toppings x. If it is, we add that topping to the pizza. If the requested topping is not in the list of available toppings, the else block will run y. The else block prints a message telling the user which toppings are unavailable. This code syntax produces clean, informative output: Adding mushrooms. Sorry, we don't have french fries. Adding extra cheese. Finished making your pizza! In just a few lines of code, we’ve managed a real-world situation pretty effectively!

if Statements 93 try It yourse lf 5-8. Hello Admin: Make a list of five or more usernames, including the name 'admin' Imagine you are writing code that will print a greeting to each user after they log in to a website Loop through the list, and print a greeting to each user: • If the username is 'admin', print a special greeting, such as Hello admin, would you like to see a status report? • Otherwise, print a generic greeting, such as Hello Eric, thank you for log- ging in again. 5-9. No Users: Add an if test to hello_admin.py to make sure the list of users is not empty • If the list is empty, print the message We need to find some users! • Remove all of the usernames from your list, and make sure the correct message is printed 5-10. Checking Usernames: Do the following to create a program that simulates how websites ensure that everyone has a unique username • Make a list of five or more usernames called current_users • Make another list of five usernames called new_users Make sure one or two of the new usernames are also in the current_users list • Loop through the new_users list to see if each new username has already been used If it has, print a message that the person will need to enter a new username If a username has not been used, print a message saying that the username is available • Make sure your comparison is case insensitive If 'John' has been used, 'JOHN' should not be accepted 5-11. Ordinal Numbers: Ordinal numbers indicate their position in a list, such as 1st or 2nd Most ordinal numbers end in th, except 1, 2, and 3 • Store the numbers 1 through 9 in a list • Loop through the list • Use an if-elif-else chain inside the loop to print the proper ordinal end- ing for each number Your output should read "1st 2nd 3rd 4th 5th 6th 7th 8th 9th", and each result should be on a separate line

94 Chapter 5 styling your if statements In every example in this chapter, you’ve seen good styling habits. The only recommendation PEP 8 provides for styling conditional tests is to use a single space around comparison operators, such as ==, >=, <=. For example: if age < 4: is better than: if age<4: Such spacing does not affect the way Python interprets your code; it just makes your code easier for you and others to read. try It yourse lf 5-12. Styling if statements: Review the programs you wrote in this chapter, and make sure you styled your conditional tests appropriately 5-13. Your Ideas: At this point, you’re a more capable programmer than you were when you started this book Now that you have a better sense of how real-world situations are modeled in programs, you might be thinking of some problems you could solve with your own programs Record any new ideas you have about problems you might want to solve as your programming skills con- tinue to improve Consider games you might want to write, data sets you might want to explore, and web applications you’d like to create summary In this chapter you learned how to write conditional tests, which always evaluate to True or False. You learned to write simple if statements, if-else chains, and if-elif-else chains. You began using these structures to identify particular conditions you needed to test and to know when those conditions have been met in your programs. You learned to handle certain items in a list differently than all other items while continuing to utilize the efficiency of a for loop. You also revisited Python’s style recommendations to ensure that your increasingly complex programs are still relatively easy to read and understand. In Chapter 6 you’ll learn about Python’s dictionaries. A dictionary is similar to a list, but it allows you to connect pieces of information. You’ll learn to build dictionaries, loop through them, and use them in combina- tion with lists and if statements. Learning about dictionaries will enable you to model an even wider variety of real-world situations.

6D I C t I o n a r I e s In this chapter you’ll learn how to use Python’s dictionaries, which allow you to connect pieces of related information. You’ll learn how to access the information once it’s in a dictionary and how to modify that information. Because dictionaries can store an almost limitless amount of information, I’ll show you how to loop through the data in a dictionary. Additionally, you’ll learn to nest dictionaries inside lists, lists inside dictionaries, and even dictionaries inside other dictionaries. Understanding dictionaries allows you to model a variety of real-world objects more accurately. You’ll be able to create a dictionary representing a person and then store as much information as you want about that person. You can store their name, age, location, profession, and any other aspect of a person you can describe. You’ll be able to store any two kinds of informa- tion that can be matched up, such as a list of words and their meanings, a list of people’s names and their favorite numbers, a list of mountains and their elevations, and so forth.

96 Chapter 6 a simple dictionary Consider a game featuring aliens that can have different colors and point values. This simple dictionary stores information about a particular alien: alien.py alien_0 = {'color': 'green', 'points': 5} print(alien_0['color']) print(alien_0['points']) The dictionary alien_0 stores the alien’s color and point value. The two print statements access and display that information, as shown here: green 5 As with most new programming concepts, using dictionaries takes practice. Once you’ve worked with dictionaries for a bit you’ll soon see how effectively they can model real-world situations. working with dictionaries A dictionary in Python is a collection of key-value pairs. Each key is connected to a value, and you can use a key to access the value associated with that key. A key’s value can be a number, a string, a list, or even another dictionary. In fact, you can use any object that you can create in Python as a value in a dictionary. In Python, a dictionary is wrapped in braces, {}, with a series of key- value pairs inside the braces, as shown in the earlier example: alien_0 = {'color': 'green', 'points': 5} A key-value pair is a set of values associated with each other. When you provide a key, Python returns the value associated with that key. Every key is connected to its value by a colon, and individual key-value pairs are sepa- rated by commas. You can store as many key-value pairs as you want in a dictionary. The simplest dictionary has exactly one key-value pair, as shown in this modified version of the alien_0 dictionary: alien_0 = {'color': 'green'} This dictionary stores one piece of information about alien_0, namely the alien’s color. The string 'color' is a key in this dictionary, and its associ- ated value is 'green'.

Dictionaries 97 Accessing Values in a Dictionary To get the value associated with a key, give the name of the dictionary and then place the key inside a set of square brackets, as shown here: alien_0 = {'color': 'green'} print(alien_0['color']) This returns the value associated with the key 'color' from the diction- ary alien_0: green You can have an unlimited number of key-value pairs in a dictionary. For example, here’s the original alien_0 dictionary with two key-value pairs: alien_0 = {'color': 'green', 'points': 5} Now you can access either the color or the point value of alien_0. If a player shoots down this alien, you can look up how many points they should earn using code like this: alien_0 = {'color': 'green', 'points': 5} u new_points = alien_0['points'] v print("You just earned " + str(new_points) + " points!") Once the dictionary has been defined, the code at u pulls the value associated with the key 'points' from the dictionary. This value is then stored in the variable new_points. The line at v converts this integer value to a string and prints a statement about how many points the player just earned: You just earned 5 points! If you run this code every time an alien is shot down, the alien’s point value will be retrieved. Adding New Key-Value Pairs Dictionaries are dynamic structures, and you can add new key-value pairs to a dictionary at any time. For example, to add a new key-value pair, you would give the name of the dictionary followed by the new key in square brackets along with the new value. Let’s add two new pieces of information to the alien_0 dictionary: the alien’s x- and y-coordinates, which will help us display the alien in a par- ticular position on the screen. Let’s place the alien on the left edge of the screen, 25 pixels down from the top. Because screen coordinates usually start at the upper-left corner of the screen, we’ll place the alien on the left

98 Chapter 6 edge of the screen by setting the x-coordinate to 0 and 25 pixels from the top by setting its y-coordinate to positive 25, as shown here: alien_0 = {'color': 'green', 'points': 5} print(alien_0) u alien_0['x_position'] = 0 v alien_0['y_position'] = 25 print(alien_0) We start by defining the same dictionary that we’ve been working with. We then print this dictionary, displaying a snapshot of its informa- tion. At u we add a new key-value pair to the dictionary: key 'x_position' and value 0. We do the same for key 'y_position' at v. When we print the modified dictionary, we see the two additional key-value pairs: {'color': 'green', 'points': 5} {'color': 'green', 'points': 5, 'y_position': 25, 'x_position': 0} The final version of the dictionary contains four key-value pairs. The original two specify color and point value, and two more specify the alien’s position. Notice that the order of the key-value pairs does not match the order in which we added them. Python doesn’t care about the order in which you store each key-value pair; it cares only about the connection between each key and its value. Starting with an Empty Dictionary It’s sometimes convenient, or even necessary, to start with an empty diction- ary and then add each new item to it. To start filling an empty dictionary, define a dictionary with an empty set of braces and then add each key-value pair on its own line. For example, here’s how to build the alien_0 dictionary using this approach: alien_0 = {} alien_0['color'] = 'green' alien_0['points'] = 5 print(alien_0) Here we define an empty alien_0 dictionary, and then add color and point values to it. The result is the dictionary we’ve been using in previous examples: {'color': 'green', 'points': 5} Typically, you’ll use empty dictionaries when storing user-supplied data in a dictionary or when you write code that generates a large number of key-value pairs automatically.

Dictionaries 99 Modifying Values in a Dictionary To modify a value in a dictionary, give the name of the dictionary with the key in square brackets and then the new value you want associated with that key. For example, consider an alien that changes from green to yellow as a game progresses: alien_0 = {'color': 'green'} print("The alien is " + alien_0['color'] + ".") alien_0['color'] = 'yellow' print("The alien is now " + alien_0['color'] + ".") We first define a dictionary for alien_0 that contains only the alien’s color; then we change the value associated with the key 'color' to 'yellow'. The output shows that the alien has indeed changed from green to yellow: The alien is green. The alien is now yellow. For a more interesting example, let’s track the position of an alien that can move at different speeds. We’ll store a value representing the alien’s current speed and then use it to determine how far to the right the alien should move: alien_0 = {'x_position': 0, 'y_position': 25, 'speed': 'medium'} print("Original x-position: " + str(alien_0['x_position'])) # Move the alien to the right. # Determine how far to move the alien based on its current speed. u if alien_0['speed'] == 'slow': x_increment = 1 elif alien_0['speed'] == 'medium': x_increment = 2 else: # This must be a fast alien. x_increment = 3 # The new position is the old position plus the increment. v alien_0['x_position'] = alien_0['x_position'] + x_increment print("New x-position: " + str(alien_0['x_position'])) We start by defining an alien with an initial x position and y position, and a speed of 'medium'. We’ve omitted the color and point values for the sake of simplicity, but this example would work the same way if you included those key-value pairs as well. We also print the original value of x_position to see how far the alien moves to the right. At u, an if-elif-else chain determines how far the alien should move to the right and stores this value in the variable x_increment. If the alien’s speed is 'slow', it moves one unit to the right; if the speed is 'medium', it moves two

100 Chapter 6 units to the right; and if it’s 'fast', it moves three units to the right. Once the increment has been calculated, it’s added to the value of x_position at v, and the result is stored in the dictionary’s x_position. Because this is a medium-speed alien, its position shifts two units to the right: Original x-position: 0 New x-position: 2 This technique is pretty cool: by changing one value in the alien’s dic- tionary, you can change the overall behavior of the alien. For example, to turn this medium-speed alien into a fast alien, you would add the line: alien_0['speed'] = fast The if-elif-else block would then assign a larger value to x_increment the next time the code runs. Removing Key-Value Pairs When you no longer need a piece of information that’s stored in a diction- ary, you can use the del statement to completely remove a key-value pair. All del needs is the name of the dictionary and the key that you want to remove. For example, let’s remove the key 'points' from the alien_0 dictionary along with its value: alien_0 = {'color': 'green', 'points': 5} print(alien_0) u del alien_0['points'] print(alien_0) The line at u tells Python to delete the key 'points' from the dictionary alien_0 and to remove the value associated with that key as well. The output shows that the key 'points' and its value of 5 are deleted from the diction- ary, but the rest of the dictionary is unaffected: {'color': 'green', 'points': 5} {'color': 'green'} n o t e Be aware that the deleted key-value pair is removed permanently. A Dictionary of Similar Objects The previous example involved storing different kinds of information about one object, an alien in a game. You can also use a dictionary to store one kind of information about many objects. For example, say you want to poll a

Dictionaries 101 number of people and ask them what their favorite programming language is. A dictionary is useful for storing the results of a simple poll, like this: favorite_languages = { 'jen': 'python', 'sarah': 'c', 'edward': 'ruby', 'phil': 'python', } As you can see, we’ve broken a larger dictionary into several lines. Each key is the name of a person who responded to the poll, and each value is their language choice. When you know you’ll need more than one line to define a dictionary, press enter after the opening brace. Then indent the next line one level (four spaces), and write the first key-value pair, followed by a comma. From this point forward when you press enter, your text editor should automatically indent all subsequent key-value pairs to match the first key-value pair. Once you’ve finished defining the dictionary, add a closing brace on a new line after the last key-value pair and indent it one level so it aligns with the keys in the dictionary. It’s good practice to include a comma after the last key-value pair as well, so you’re ready to add a new key-value pair on the next line. n o t e Most editors have some functionality that helps you format extended lists and dic- tionaries in a similar manner to this example. Other acceptable ways to format long dictionaries are available as well, so you may see slightly different formatting in your editor, or in other sources. To use this dictionary, given the name of a person who took the poll, you can easily look up their favorite language: favorite_ favorite_languages = { languages.py 'jen': 'python', 'sarah': 'c', 'edward': 'ruby', 'phil': 'python', } u print("Sarah's favorite language is " + v favorite_languages['sarah'].title() + w ".") To see which language Sarah chose, we ask for the value at: favorite_languages['sarah'] This syntax is used in the print statement at v, and the output shows Sarah’s favorite language: Sarah's favorite language is C.

102 Chapter 6 This example also shows how you can break up a long print statement over several lines. The word print is shorter than most dictionary names, so it makes sense to include the first part of what you want to print right after the opening parenthesis u. Choose an appropriate point at which to break what’s being printed, and add a concatenation operator (+) at the end of the first line v. Press enter and then press tab to align all subsequent lines at one indentation level under the print statement. When you’ve finished composing your output, you can place the closing parenthesis on the last line of the print block w. try It yourse lf 6-1. Person: Use a dictionary to store information about a person you know Store their first name, last name, age, and the city in which they live You should have keys such as first_name, last_name, age, and city Print each piece of information stored in your dictionary 6-2. Favorite Numbers: Use a dictionary to store people’s favorite numbers Think of five names, and use them as keys in your dictionary Think of a favorite number for each person, and store each as a value in your dictionary Print each person’s name and their favorite number For even more fun, poll a few friends and get some actual data for your program 6-3. Glossary: A Python dictionary can be used to model an actual dictionary However, to avoid confusion, let’s call it a glossary • Think of five programming words you’ve learned about in the previous chapters Use these words as the keys in your glossary, and store their meanings as values • Print each word and its meaning as neatly formatted output You might print the word followed by a colon and then its meaning, or print the word on one line and then print its meaning indented on a second line Use the newline character (\n) to insert a blank line between each word-meaning pair in your output looping through a dictionary A single Python dictionary can contain just a few key-value pairs or millions of pairs. Because a dictionary can contain large amounts of data, Python lets you loop through a dictionary. Dictionaries can be used to store information in a variety of ways; therefore, several different ways exist to loop through them. You can loop through all of a dictionary’s key-value pairs, through its keys, or through its values.

Dictionaries 103 Looping Through All Key-Value Pairs Before we explore the different approaches to looping, let’s consider a new dictionary designed to store information about a user on a website. The following dictionary would store one person’s username, first name, and last name: user_0 = { 'username': 'efermi', 'first': 'enrico', 'last': 'fermi', } You can access any single piece of information about user_0 based on what you’ve already learned in this chapter. But what if you wanted to see everything stored in this user’s dictionary? To do so, you could loop through the dictionary using a for loop: user.py user_0 = { 'username': 'efermi', 'first': 'enrico', 'last': 'fermi', } u for key, value in user_0.items(): v print("\nKey: " + key) w print("Value: " + value) As shown at u, to write a for loop for a dictionary, you create names for the two variables that will hold the key and value in each key-value pair. You can choose any names you want for these two variables. This code would work just as well if you had used abbreviations for the variable names, like this: for k, v in user_0.items() The second half of the for statement at u includes the name of the dic- tionary followed by the method items(), which returns a list of key-value pairs. The for loop then stores each of these pairs in the two variables provided. In the preceding example, we use the variables to print each key v, followed by the associated value w. The "\n" in the first print statement ensures that a blank line is inserted before each key-value pair in the output: Key: last Value: fermi Key: first Value: enrico Key: username Value: efermi

104 Chapter 6 Notice again that the key-value pairs are not returned in the order in which they were stored, even when looping through a dictionary. Python doesn’t care about the order in which key-value pairs are stored; it tracks only the connections between individual keys and their values. Looping through all key-value pairs works particularly well for diction- aries like the favorite_languages.py example on page 101, which stores the same kind of information for many different keys. If you loop through the favorite_languages dictionary, you get the name of each person in the dic- tionary and their favorite programming language. Because the keys always refer to a person’s name and the value is always a language, we’ll use the variables name and language in the loop instead of key and value. This will make it easier to follow what’s happening inside the loop: favorite_ favorite_languages = { languages.py 'jen': 'python', 'sarah': 'c', 'edward': 'ruby', 'phil': 'python', } u for name, language in favorite_languages.items(): v print(name.title() + "'s favorite language is " + language.title() + ".") The code at u tells Python to loop through each key-value pair in the dictionary. As it works through each pair the key is stored in the vari- able name, and the value is stored in the variable language. These descriptive names make it much easier to see what the print statement at v is doing. Now, in just a few lines of code, we can display all of the information from the poll: Jen's favorite language is Python. Sarah's favorite language is C. Phil's favorite language is Python. Edward's favorite language is Ruby. This type of looping would work just as well if our dictionary stored the results from polling a thousand or even a million people. Looping Through All the Keys in a Dictionary The keys() method is useful when you don’t need to work with all of the values in a dictionary. Let’s loop through the favorite_languages dictionary and print the names of everyone who took the poll: favorite_languages = { 'jen': 'python', 'sarah': 'c', 'edward': 'ruby', 'phil': 'python', }

Dictionaries 105 u for name in favorite_languages.keys(): print(name.title()) The line at u tells Python to pull all the keys from the dictionary favorite_languages and store them one at a time in the variable name. The output shows the names of everyone who took the poll: Jen Sarah Phil Edward Looping through the keys is actually the default behavior when looping through a dictionary, so this code would have exactly the same output if you wrote . . . for name in favorite_languages: rather than . . . for name in favorite_languages.keys(): You can choose to use the keys() method explicitly if it makes your code easier to read, or you can omit it if you wish. You can access the value associated with any key you care about inside the loop by using the current key. Let’s print a message to a couple of friends about the languages they chose. We’ll loop through the names in the diction- ary as we did previously, but when the name matches one of our friends, we’ll display a message about their favorite language: favorite_languages = { 'jen': 'python', 'sarah': 'c', 'edward': 'ruby', 'phil': 'python', } u friends = ['phil', 'sarah'] for name in favorite_languages.keys(): print(name.title()) v if name in friends: print(" Hi " + name.title() + ", I see your favorite language is " + w favorite_languages[name].title() + "!") At u we make a list of friends that we want to print a message to. Inside the loop, we print each person’s name. Then at v we check to see whether the name we are working with is in the list friends. If it is, we print a special greeting, including a reference to their language choice. To access

106 Chapter 6 the favorite language at w, we use the name of the dictionary and the cur- rent value of name as the key. Everyone’s name is printed, but our friends receive a special message: Edward Phil Hi Phil, I see your favorite language is Python! Sarah Hi Sarah, I see your favorite language is C! Jen You can also use the keys() method to find out if a particular person was polled. This time, let’s find out if Erin took the poll: favorite_languages = { 'jen': 'python', 'sarah': 'c', 'edward': 'ruby', 'phil': 'python', } u if 'erin' not in favorite_languages.keys(): print("Erin, please take our poll!") The keys() method isn’t just for looping: It actually returns a list of all the keys, and the line at u simply checks if 'erin' is in this list. Because she’s not, a message is printed inviting her to take the poll: Erin, please take our poll! Looping Through a Dictionary’s Keys in Order A dictionary always maintains a clear connection between each key and its associated value, but you never get the items from a dictionary in any predictable order. That’s not a problem, because you’ll usually just want to obtain the correct value associated with each key. One way to return items in a certain order is to sort the keys as they’re returned in the for loop. You can use the sorted() function to get a copy of the keys in order: favorite_languages = { 'jen': 'python', 'sarah': 'c', 'edward': 'ruby', 'phil': 'python', } for name in sorted(favorite_languages.keys()): print(name.title() + ", thank you for taking the poll.")

Dictionaries 107 This for statement is like other for statements except that we’ve wrapped the sorted() function around the dictionary.keys() method. This tells Python to list all keys in the dictionary and sort that list before looping through it. The output shows everyone who took the poll with the names displayed in order: Edward, thank you for taking the poll. Jen, thank you for taking the poll. Phil, thank you for taking the poll. Sarah, thank you for taking the poll. Looping Through All Values in a Dictionary If you are primarily interested in the values that a dictionary contains, you can use the values() method to return a list of values without any keys. For example, say we simply want a list of all languages chosen in our pro- gramming language poll without the name of the person who chose each language: favorite_languages = { 'jen': 'python', 'sarah': 'c', 'edward': 'ruby', 'phil': 'python', } print("The following languages have been mentioned:") for language in favorite_languages.values(): print(language.title()) The for statement here pulls each value from the dictionary and stores it in the variable language. When these values are printed, we get a list of all chosen languages: The following languages have been mentioned: Python C Python Ruby This approach pulls all the values from the dictionary without checking for repeats. That might work fine with a small number of values, but in a poll with a large number of respondents, this would result in a very repeti- tive list. To see each language chosen without repetition, we can use a set. A set is similar to a list except that each item in the set must be unique: favorite_languages = { 'jen': 'python', 'sarah': 'c', 'edward': 'ruby',

108 Chapter 6 'phil': 'python', } print("The following languages have been mentioned:") u for language in set(favorite_languages.values()): print(language.title()) When you wrap set() around a list that contains duplicate items, Python identifies the unique items in the list and builds a set from those items. At u we use set() to pull out the unique languages in favorite_languages.values(). The result is a nonrepetitive list of languages that have been mentioned by people taking the poll: The following languages have been mentioned: Python C Ruby As you continue learning about Python, you’ll often find a built-in fea- ture of the language that helps you do exactly what you want with your data. try It yourse lf 6-4. Glossary 2: Now that you know how to loop through a dictionary, clean up the code from Exercise 6-3 (page 102) by replacing your series of print statements with a loop that runs through the dictionary’s keys and values When you’re sure that your loop works, add five more Python terms to your glossary When you run your program again, these new words and meanings should automatically be included in the output 6-5. Rivers: Make a dictionary containing three major rivers and the country each river runs through One key-value pair might be 'nile': 'egypt' • Use a loop to print a sentence about each river, such as The Nile runs through Egypt • Use a loop to print the name of each river included in the dictionary • Use a loop to print the name of each country included in the dictionary 6-6. Polling: Use the code in favorite_languages.py (page 104) • Make a list of people who should take the favorite languages poll Include some names that are already in the dictionary and some that are not • Loop through the list of people who should take the poll If they have already taken the poll, print a message thanking them for responding If they have not yet taken the poll, print a message inviting them to take the poll

Dictionaries 109 nesting Sometimes you’ll want to store a set of dictionaries in a list or a list of items as a value in a dictionary. This is called nesting. You can nest a set of dictionaries inside a list, a list of items inside a dictionary, or even a dictionary inside another dictionary. Nesting is a powerful feature, as the following examples will demonstrate. A List of Dictionaries The alien_0 dictionary contains a variety of information about one alien, but it has no room to store information about a second alien, much less a screen full of aliens. How can you manage a fleet of aliens? One way is to make a list of aliens in which each alien is a dictionary of information about that alien. For example, the following code builds a list of three aliens: aliens.py alien_0 = {'color': 'green', 'points': 5} alien_1 = {'color': 'yellow', 'points': 10} alien_2 = {'color': 'red', 'points': 15} u aliens = [alien_0, alien_1, alien_2] for alien in aliens: print(alien) We first create three dictionaries, each representing a different alien. At u we pack each of these dictionaries into a list called aliens. Finally, we loop through the list and print out each alien: {'color': 'green', 'points': 5} {'color': 'yellow', 'points': 10} {'color': 'red', 'points': 15} A more realistic example would involve more than three aliens with code that automatically generates each alien. In the following example we use range() to create a fleet of 30 aliens: # Make an empty list for storing aliens. aliens = [] # Make 30 green aliens. u for alien_number in range(30): v new_alien = {'color': 'green', 'points': 5, 'speed': 'slow'} w aliens.append(new_alien) # Show the first 5 aliens: x for alien in aliens[:5]: print(alien) print("...") # Show how many aliens have been created. y print("Total number of aliens: " + str(len(aliens)))

110 Chapter 6 This example begins with an empty list to hold all of the aliens that will be created. At u range() returns a set of numbers, which just tells Python how many times we want the loop to repeat. Each time the loop runs we create a new alien v and then append each new alien to the list aliens w. At x we use a slice to print the first five aliens, and then at y we print the length of the list to prove we’ve actually generated the full fleet of 30 aliens: {'speed': 'slow', 'color': 'green', 'points': 5} {'speed': 'slow', 'color': 'green', 'points': 5} {'speed': 'slow', 'color': 'green', 'points': 5} {'speed': 'slow', 'color': 'green', 'points': 5} {'speed': 'slow', 'color': 'green', 'points': 5} ... Total number of aliens: 30 These aliens all have the same characteristics, but Python considers each one a separate object, which allows us to modify each alien individually. How might you work with a set of aliens like this? Imagine that one aspect of a game has some aliens changing color and moving faster as the game progresses. When it’s time to change colors, we can use a for loop and an if statement to change the color of aliens. For example, to change the first three aliens to yellow, medium-speed aliens worth 10 points each, we could do this: # Make an empty list for storing aliens. aliens = [] # Make 30 green aliens. for alien_number in range (0,30): new_alien = {'color': 'green', 'points': 5, 'speed': 'slow'} aliens.append(new_alien) for alien in aliens[0:3]: if alien['color'] == 'green': alien['color'] = 'yellow' alien['speed'] = 'medium' alien['points'] = 10 # Show the first 5 aliens: for alien in aliens[0:5]: print(alien) print("...") Because we want to modify the first three aliens, we loop through a slice that includes only the first three aliens. All of the aliens are green now but that won’t always be the case, so we write an if statement to make sure

Dictionaries 111 we’re only modifying green aliens. If the alien is green, we change the color to 'yellow', the speed to 'medium', and the point value to 10, as shown in the following output: {'speed': 'medium', 'color': 'yellow', 'points': 10} {'speed': 'medium', 'color': 'yellow', 'points': 10} {'speed': 'medium', 'color': 'yellow', 'points': 10} {'speed': 'slow', 'color': 'green', 'points': 5} {'speed': 'slow', 'color': 'green', 'points': 5} ... You could expand this loop by adding an elif block that turns yellow aliens into red, fast-moving ones worth 15 points each. Without showing the entire program again, that loop would look like this: for alien in aliens[0:3]: if alien['color'] == 'green': alien['color'] = 'yellow' alien['speed'] = 'medium' alien['points'] = 10 elif alien['color'] == 'yellow': alien['color'] = 'red' alien['speed'] = 'fast' alien['points'] = 15 It’s common to store a number of dictionaries in a list when each dic- tionary contains many kinds of information about one object. For example, you might create a dictionary for each user on a website, as we did in user.py on page 103, and store the individual dictionaries in a list called users. All of the dictionaries in the list should have an identical structure so you can loop through the list and work with each dictionary object in the same way. A List in a Dictionary Rather than putting a dictionary inside a list, it’s sometimes useful to put a list inside a dictionary. For example, consider how you might describe a pizza that someone is ordering. If you were to use only a list, all you could really store is a list of the pizza’s toppings. With a dictionary, a list of top- pings can be just one aspect of the pizza you’re describing. In the following example, two kinds of information are stored for each pizza: a type of crust and a list of toppings. The list of toppings is a value associated with the key 'toppings'. To use the items in the list, we give the name of the dictionary and the key 'toppings', as we would any value in the dictionary. Instead of returning a single value, we get a list of toppings: pizza.py # Store information about a pizza being ordered. u pizza = { 'crust': 'thick', 'toppings': ['mushrooms', 'extra cheese'], }

112 Chapter 6 # Summarize the order. v print("You ordered a " + pizza['crust'] + "-crust pizza " + "with the following toppings:") w for topping in pizza['toppings']: print("\t" + topping) We begin at u with a dictionary that holds information about a pizza that has been ordered. One key in the dictionary is 'crust', and the associ- ated value is the string 'thick'. The next key, 'toppings', has a list as its value that stores all requested toppings. At v we summarize the order before building the pizza. To print the toppings, we write a for loop w. To access the list of toppings, we use the key 'toppings', and Python grabs the list of toppings from the dictionary. The following output summarizes the pizza that we plan to build: You ordered a thick-crust pizza with the following toppings: mushrooms extra cheese You can nest a list inside a dictionary any time you want more than one value to be associated with a single key in a dictionary. In the earlier example of favorite programming languages, if we were to store each person’s responses in a list, people could choose more than one favorite language. When we loop through the dictionary, the value associated with each person would be a list of languages rather than a single language. Inside the dictionary’s for loop, we use another for loop to run through the list of languages associated with each person: u favorite_languages = { 'jen': ['python', 'ruby'], 'sarah': ['c'], 'edward': ['ruby', 'go'], 'phil': ['python', 'haskell'], } v for name, languages in favorite_languages.items(): print("\n" + name.title() + "'s favorite languages are:") w for language in languages: print("\t" + language.title()) As you can see at u the value associated with each name is now a list. Notice that some people have one favorite language and others have multiple favorites. When we loop through the dictionary at v, we use the variable name languages to hold each value from the dictionary, because we know that each value will be a list. Inside the main dictionary loop, we use favorite_ languages.py

Dictionaries 113 another for loop w to run through each person’s list of favorite languages. Now each person can list as many favorite languages as they like: Jen's favorite languages are: Python Ruby Sarah's favorite languages are: C Phil's favorite languages are: Python Haskell Edward's favorite languages are: Ruby Go To refine this program even further, you could include an if statement at the beginning of the dictionary’s for loop to see whether each person has more than one favorite language by examining the value of len(languages). If a person has more than one favorite, the output would stay the same. If the person has only one favorite language, you could change the wording to reflect that. For example, you could say Sarah's favorite language is C. n o t e You should not nest lists and dictionaries too deeply. If you’re nesting items much deeper than what you see in the preceding examples or you’re working with someone else’s code with significant levels of nesting, most likely a simpler way to solve the problem exists. A Dictionary in a Dictionary You can nest a dictionary inside another dictionary, but your code can get complicated quickly when you do. For example, if you have several users for a website, each with a unique username, you can use the usernames as the keys in a dictionary. You can then store information about each user by using a dictionary as the value associated with their username. In the fol- lowing listing, we store three pieces of information about each user: their first name, last name, and location. We’ll access this information by looping through the usernames and the dictionary of information associated with each username: many_users.py users = { 'aeinstein': { 'first': 'albert', 'last': 'einstein', 'location': 'princeton', },

114 Chapter 6 'mcurie': { 'first': 'marie', 'last': 'curie', 'location': 'paris', }, } u for username, user_info in users.items(): v print("\nUsername: " + username) w full_name = user_info['first'] + " " + user_info['last'] location = user_info['location'] x print("\tFull name: " + full_name.title()) print("\tLocation: " + location.title()) We first define a dictionary called users with two keys: one each for the usernames 'aeinstein' and 'mcurie'. The value associated with each key is a dictionary that includes each user’s first name, last name, and location. At u we loop through the users dictionary. Python stores each key in the variable username, and the dictionary associated with each username goes into the variable user_info. Once inside the main dictionary loop, we print the username at v. At w we start accessing the inner dictionary. The variable user_info, which contains the dictionary of user information, has three keys: 'first', 'last', and 'location'. We use each key to generate a neatly formatted full name and location for each person, and then print a summary of what we know about each user x: Username: aeinstein Full name: Albert Einstein Location: Princeton Username: mcurie Full name: Marie Curie Location: Paris Notice that the structure of each user’s dictionary is identical. Although not required by Python, this structure makes nested dictionaries easier to work with. If each user’s dictionary had different keys, the code inside the for loop would be more complicated. try It yourse lf 6-7. People: Start with the program you wrote for Exercise 6-1 (page 102) Make two new dictionaries representing different people, and store all three dictionaries in a list called people Loop through your list of people As you loop through the list, print everything you know about each person

Dictionaries 115 6-8. Pets: Make several dictionaries, where the name of each dictionary is the name of a pet In each dictionary, include the kind of animal and the owner’s name Store these dictionaries in a list called pets Next, loop through your list and as you do print everything you know about each pet 6-9. Favorite Places: Make a dictionary called favorite_places Think of three names to use as keys in the dictionary, and store one to three favorite places for each person To make this exercise a bit more interesting, ask some friends to name a few of their favorite places Loop through the dictionary, and print each person’s name and their favorite places 6-10. Favorite Numbers: Modify your program from Exercise 6-2 (page 102) so each person can have more than one favorite number Then print each person’s name along with their favorite numbers 6-11. Cities: Make a dictionary called cities Use the names of three cities as keys in your dictionary Create a dictionary of information about each city and include the country that the city is in, its approximate population, and one fact about that city The keys for each city’s dictionary should be something like country, population, and fact Print the name of each city and all of the infor- mation you have stored about it 6-12. Extensions: We’re now working with examples that are complex enough that they can be extended in any number of ways Use one of the example pro- grams from this chapter, and extend it by adding new keys and values, chang- ing the context of the program or improving the formatting of the output summary In this chapter you learned how to define a dictionary and how to work with the information stored in a dictionary. You learned how to access and modify individual elements in a dictionary, and how to loop through all of the information in a dictionary. You learned to loop through a dictionary’s key-value pairs, its keys, and its values. You also learned how to nest multiple dictionaries in a list, nest lists in a dictionary, and nest a dictionary inside a dictionary. In the next chapter you’ll learn about while loops and how to accept input from people who are using your programs. This will be an exciting chapter, because you’ll learn to make all of your programs interactive: they’ll be able to respond to user input.

7u s e r I n P u t a n D w h I l e l o o P s Most programs are written to solve an end user’s problem. To do so, you usually need to get some information from the user. For a simple example, let’s say someone wants to find out whether they’re old enough to vote. If you write a program to answer this question, you need to know the user’s age before you can provide an answer. The program will need to ask the user to enter, or input, their age; once the program has this input, it can compare it to the voting age to determine if the user is old enough and then report the result. In this chapter you’ll learn how to accept user input so your program can then work with it. When your program needs a name, you’ll be able to prompt the user for a name. When your program needs a list of names, you’ll be able to prompt the user for a series of names. To do this, you’ll use the input() function. You’ll also learn how to keep programs running as long as users want them to, so they can enter as much information as they need to; then, your program can work with that information. You’ll use Python’s while loop to keep programs running as long as certain conditions remain true.

118 Chapter 7 With the ability to work with user input and the ability to control how long your programs run, you’ll be able to write fully interactive programs. how the input() function works The input() function pauses your program and waits for the user to enter some text. Once Python receives the user’s input, it stores it in a variable to make it convenient for you to work with. For example, the following program asks the user to enter some text, then displays that message back to the user: parrot.py message = input("Tell me something, and I will repeat it back to you: ") print(message) The input() function takes one argument: the prompt, or instructions, that we want to display to the user so they know what to do. In this example, when Python runs the first line, the user sees the prompt Tell me something, and I will repeat it back to you: . The program waits while the user enters their response and continues after the user presses enter. The response is stored in the variable message, then print(message) displays the input back to the user: Tell me something, and I will repeat it back to you: Hello everyone! Hello everyone! n o t e Sublime Text doesn’t run programs that prompt the user for input. You can use Sublime Text to write programs that prompt for input, but you’ll need to run these programs from a terminal. See “Running Python Programs from a Terminal” on page 16. Writing Clear Prompts Each time you use the input() function, you should include a clear, easy-to- follow prompt that tells the user exactly what kind of information you’re looking for. Any statement that tells the user what to enter should work. For example: greeter.py name = input("Please enter your name: ") print("Hello, " + name + "!") Add a space at the end of your prompts (after the colon in the preced- ing example) to separate the prompt from the user’s response and to make it clear to your user where to enter their text. For example: Please enter your name: Eric Hello, Eric! Sometimes you’ll want to write a prompt that’s longer than one line. For example, you might want to tell the user why you’re asking for certain input.

User Input and while Loops 119 You can store your prompt in a variable and pass that variable to the input() function. This allows you to build your prompt over several lines, then write a clean input() statement. greeter.py prompt = "If you tell us who you are, we can personalize the messages you see." prompt += "\nWhat is your first name? " name = input(prompt) print("\nHello, " + name + "!") This example shows one way to build a multi-line string. The first line stores the first part of the message in the variable prompt. In the second line, the operator += takes the string that was stored in prompt and adds the new string onto the end. The prompt now spans two lines, again with space after the question mark for clarity: If you tell us who you are, we can personalize the messages you see. What is your first name? Eric Hello, Eric! Using int() to Accept Numerical Input When you use the input() function, Python interprets everything the user enters as a string. Consider the following interpreter session, which asks for the user’s age: >>> age = input("How old are you? ") How old are you? 21 >>> age '21' The user enters the number 21, but when we ask Python for the value of age, it returns '21', the string representation of the numerical value entered. We know Python interpreted the input as a string because the number is now enclosed in quotes. If all you want to do is print the input, this works well. But if you try to use the input as a number, you’ll get an error: >>> age = input("How old are you? ") How old are you? 21 u >>> age >= 18 Traceback (most recent call last): File "<stdin>", line 1, in <module> v TypeError: unorderable types: str() >= int() When you try to use the input to do a numerical comparison u, Python produces an error because it can’t compare a string to an integer: the string '21' that’s stored in age can’t be compared to the numerical value 18 v.

120 Chapter 7 We can resolve this issue by using the int() function, which tells Python to treat the input as a numerical value. The int() function con- verts a string representation of a number to a numerical representation, as shown here: >>> age = input("How old are you? ") How old are you? 21 u >>> age = int(age) >>> age >= 18 True In this example, when we enter 21 at the prompt, Python interprets the number as a string, but the value is then converted to a numerical represen- tation by int() u. Now Python can run the conditional test: it compares age (which now contains the numerical value 21) and 18 to see if age is greater than or equal to 18. This test evaluates to True. How do you use the int() function in an actual program? Consider a program that determines whether people are tall enough to ride a roller coaster: rollercoaster.py height = input("How tall are you, in inches? ") height = int(height) if height >= 36: print("\nYou're tall enough to ride!") else: print("\nYou'll be able to ride when you're a little older.") The program can compare height to 36 because height = int(height) converts the input value to a numerical representation before the compari- son is made. If the number entered is greater than or equal to 36, we tell the user that they’re tall enough: How tall are you, in inches? 71 You're tall enough to ride! When you use numerical input to do calculations and comparisons, be sure to convert the input value to a numerical representation first. The Modulo Operator A useful tool for working with numerical information is the modulo operator (%), which divides one number by another number and returns the remainder: >>> 4 % 3 1 >>> 5 % 3 2 >>> 6 % 3 0

User Input and while Loops 121 >>> 7 % 3 1 The modulo operator doesn’t tell you how many times one number fits into another; it just tells you what the remainder is. When one number is divisible by another number, the remainder is 0, so the modulo operator always returns 0. You can use this fact to determine if a number is even or odd: even_or_odd.py number = input("Enter a number, and I'll tell you if it's even or odd: ") number = int(number) if number % 2 == 0: print("\nThe number " + str(number) + " is even.") else: print("\nThe number " + str(number) + " is odd.") Even numbers are always divisible by two, so if the modulo of a number and two is zero (here, if number % 2 == 0) the number is even. Otherwise, it’s odd. Enter a number, and I'll tell you if it's even or odd: 42 The number 42 is even. Accepting Input in Python 2.7 If you’re using Python 2.7, you should use the raw_input() function when prompting for user input. This function interprets all input as a string, just as input() does in Python 3. Python 2.7 has an input() function as well, but this function interprets the user’s input as Python code and attempts to run the input. At best you’ll get an error that Python doesn’t understand the input; at worst you’ll run code that you didn’t intend to run. If you’re using Python 2.7, use raw_input() instead of input(). try It yourse lf 7-1. Rental Car: Write a program that asks the user what kind of rental car they would like Print a message about that car, such as “Let me see if I can find you a Subaru ” 7-2. Restaurant Seating: Write a program that asks the user how many people are in their dinner group If the answer is more than eight, print a message say- ing they’ll have to wait for a table Otherwise, report that their table is ready 7-3. Multiples of Ten: Ask the user for a number, and then report whether the number is a multiple of 10 or not

122 Chapter 7 Introducing while loops The for loop takes a collection of items and executes a block of code once for each item in the collection. In contrast, the while loop runs as long as, or while, a certain condition is true. The while Loop in Action You can use a while loop to count up through a series of numbers. For example, the following while loop counts from 1 to 5: counting.py current_number = 1 while current_number <= 5: print(current_number) current_number += 1 In the first line, we start counting from 1 by setting the value of current_number to 1. The while loop is then set to keep running as long as the value of current_number is less than or equal to 5. The code inside the loop prints the value of current_number and then adds 1 to that value with current_number += 1. (The += operator is shorthand for current_number = current_number + 1.) Python repeats the loop as long as the condition current_number <= 5 is true. Because 1 is less than 5, Python prints 1 and then adds 1, mak- ing the current number 2. Because 2 is less than 5, Python prints 2 and adds 1 again, making the current number 3, and so on. Once the value of current_number is greater than 5, the loop stops running and the program ends: 1 2 3 4 5 The programs you use every day most likely contain while loops. For example, a game needs a while loop to keep running as long as you want to keep playing, and so it can stop running as soon as you ask it to quit. Programs wouldn’t be fun to use if they stopped running before we told them to or kept running even after we wanted to quit, so while loops are quite useful. Letting the User Choose When to Quit We can make the parrot.py program run as long as the user wants by putting most of the program inside a while loop. We’ll define a quit value and then keep the program running as long as the user has not entered the quit value: parrot.py u prompt = "\nTell me something, and I will repeat it back to you:" prompt += "\nEnter 'quit' to end the program. "

User Input and while Loops 123 v message = "" w while message != 'quit': message = input(prompt) print(message) At u, we define a prompt that tells the user their two options: enter- ing a message or entering the quit value (in this case, 'quit'). Then we set up a variable message v to store whatever value the user enters. We define message as an empty string, "", so Python has something to check the first time it reaches the while line. The first time the program runs and Python reaches the while statement, it needs to compare the value of message to 'quit', but no user input has been entered yet. If Python has nothing to compare, it won’t be able to continue running the program. To solve this problem, we make sure to give message an initial value. Although it’s just an empty string, it will make sense to Python and allow it to perform the com- parison that makes the while loop work. This while loop w runs as long as the value of message is not 'quit'. The first time through the loop, message is just an empty string, so Python enters the loop. At message = input(prompt), Python displays the prompt and waits for the user to enter their input. Whatever they enter is stored in message and printed; then, Python reevaluates the condition in the while statement. As long as the user has not entered the word 'quit', the prompt is displayed again and Python waits for more input. When the user finally enters 'quit', Python stops executing the while loop and the program ends: Tell me something, and I will repeat it back to you: Enter 'quit' to end the program. Hello everyone! Hello everyone! Tell me something, and I will repeat it back to you: Enter 'quit' to end the program. Hello again. Hello again. Tell me something, and I will repeat it back to you: Enter 'quit' to end the program. quit quit This program works well, except that it prints the word 'quit' as if it were an actual message. A simple if test fixes this: prompt = "\nTell me something, and I will repeat it back to you:" prompt += "\nEnter 'quit' to end the program. " message = "" while message != 'quit': message = input(prompt) if message != 'quit': print(message)

124 Chapter 7 Now the program makes a quick check before displaying the message and only prints the message if it does not match the quit value: Tell me something, and I will repeat it back to you: Enter 'quit' to end the program. Hello everyone! Hello everyone! Tell me something, and I will repeat it back to you: Enter 'quit' to end the program. Hello again. Hello again. Tell me something, and I will repeat it back to you: Enter 'quit' to end the program. quit Using a Flag In the previous example, we had the program perform certain tasks while a given condition was true. But what about more complicated programs in which many different events could cause the program to stop running? For example, in a game, several different events can end the game. When the player runs out of ships, their time runs out, or the cities they were supposed to protect are all destroyed, the game should end. It needs to end if any one of these events happens. If many possible events might occur to stop the program, trying to test all these conditions in one while statement becomes complicated and difficult. For a program that should run only as long as many conditions are true, you can define one variable that determines whether or not the entire pro- gram is active. This variable, called a flag, acts as a signal to the program. We can write our programs so they run while the flag is set to True and stop run- ning when any of several events sets the value of the flag to False. As a result, our overall while statement needs to check only one condition: whether or not the flag is currently True. Then, all our other tests (to see if an event has occurred that should set the flag to False) can be neatly organized in the rest of the program. Let’s add a flag to parrot.py from the previous section. This flag, which we’ll call active (though you can call it anything), will monitor whether or not the program should continue running: prompt = "\nTell me something, and I will repeat it back to you:" prompt += "\nEnter 'quit' to end the program. " u active = True v while active: message = input(prompt) w if message == 'quit': active = False x else: print(message)

User Input and while Loops 125 We set the variable active to True u so the program starts in an active state. Doing so makes the while statement simpler because no comparison is made in the while statement itself; the logic is taken care of in other parts of the program. As long as the active variable remains True, the loop will con- tinue running v. In the if statement inside the while loop, we check the value of message once the user enters their input. If the user enters 'quit' w, we set active to False, and the while loop stops. If the user enters anything other than 'quit' x, we print their input as a message. This program has the same output as the previous example where we placed the conditional test directly in the while statement. But now that we have a flag to indicate whether the overall program is in an active state, it would be easy to add more tests (such as elif statements) for events that should cause active to become False. This is useful in complicated programs like games in which there may be many events that should each make the program stop running. When any of these events causes the active flag to become False, the main game loop will exit, a Game Over message can be displayed, and the player can be given the option to play again. Using break to Exit a Loop To exit a while loop immediately without running any remaining code in the loop, regardless of the results of any conditional test, use the break statement. The break statement directs the flow of your program; you can use it to con- trol which lines of code are executed and which aren’t, so the program only executes code that you want it to, when you want it to. For example, consider a program that asks the user about places they’ve visited. We can stop the while loop in this program by calling break as soon as the user enters the 'quit' value: cities.py prompt = "\nPlease enter the name of a city you have visited:" prompt += "\n(Enter 'quit' when you are finished.) " u while True: city = input(prompt) if city == 'quit': break else: print("I'd love to go to " + city.title() + "!") A loop that starts with while True u will run forever unless it reaches a break statement. The loop in this program continues asking the user to enter the names of cities they’ve been to until they enter 'quit'. When they enter 'quit', the break statement runs, causing Python to exit the loop: Please enter the name of a city you have visited: (Enter 'quit' when you are finished.) New York I'd love to go to New York!

126 Chapter 7 Please enter the name of a city you have visited: (Enter 'quit' when you are finished.) San Francisco I'd love to go to San Francisco! Please enter the name of a city you have visited: (Enter 'quit' when you are finished.) quit n o t e You can use the break statement in any of Python’s loops. For example, you could use break to quit a for loop that’s working through a list or a dictionary. Using continue in a Loop Rather than breaking out of a loop entirely without executing the rest of its code, you can use the continue statement to return to the beginning of the loop based on the result of a conditional test. For example, consider a loop that counts from 1 to 10 but prints only the odd numbers in that range: counting.py current_number = 0 while current_number < 10: u current_number += 1 if current_number % 2 == 0: continue print(current_number) First we set current_number to 0. Because it’s less than 10, Python enters the while loop. Once inside the loop, we increment the count by 1 at u, so current_number is 1. The if statement then checks the modulo of current_number and 2. If the modulo is 0 (which means current_number is divisible by 2), the continue statement tells Python to ignore the rest of the loop and return to the beginning. If the current number is not divis- ible by 2, the rest of the loop is executed and Python prints the current number: 1 3 5 7 9 Avoiding Infinite Loops Every while loop needs a way to stop running so it won’t continue to run for- ever. For example, this counting loop should count from 1 to 5: counting.py x = 1 while x <= 5: print(x) x += 1

User Input and while Loops 127 But if you accidentally omit the line x += 1 (as shown next), the loop will run forever: # This loop runs forever! x = 1 while x <= 5: print(x) Now the value of x will start at 1 but never change. As a result, the con- ditional test x <= 5 will always evaluate to True and the while loop will run forever, printing a series of 1s, like this: 1 1 1 1 --snip-- Every programmer accidentally writes an infinite while loop from time to time, especially when a program’s loops have subtle exit conditions. If your program gets stuck in an infinite loop, press ctrl-C or just close the terminal window displaying your program’s output. To avoid writing infinite loops, test every while loop and make sure the loop stops when you expect it to. If you want your program to end when the user enters a certain input value, run the program and enter that value. If the program doesn’t end, scrutinize the way your program handles the value that should cause the loop to exit. Make sure at least one part of the program can make the loop’s condition False or cause it to reach a break statement. n o t e Some editors, such as Sublime Text, have an embedded output window. This can make it difficult to stop an infinite loop, and you might have to close the editor to end the loop. try It yourse lf 7-4. Pizza Toppings: Write a loop that prompts the user to enter a series of pizza toppings until they enter a 'quit' value As they enter each topping, print a message saying you’ll add that topping to their pizza 7-5. Movie Tickets: A movie theater charges different ticket prices depending on a person’s age If a person is under the age of 3, the ticket is free; if they are between 3 and 12, the ticket is $10; and if they are over age 12, the ticket is $15 Write a loop in which you ask users their age, and then tell them the cost of their movie ticket (continued)

128 Chapter 7 7-6. Three Exits: Write different versions of either Exercise 7-4 or Exercise 7-5 that do each of the following at least once: • Use a conditional test in the while statement to stop the loop • Use an active variable to control how long the loop runs • Use a break statement to exit the loop when the user enters a 'quit' value 7-7. Infinity: Write a loop that never ends, and run it (To end the loop, press ctrl-C or close the window displaying the output ) using a while loop with lists and dictionaries So far, we’ve worked with only one piece of user information at a time. We received the user’s input and then printed the input or a response to it. The next time through the while loop, we’d receive another input value and respond to that. But to keep track of many users and pieces of informa- tion, we’ll need to use lists and dictionaries with our while loops. A for loop is effective for looping through a list, but you shouldn’t modify a list inside a for loop because Python will have trouble keeping track of the items in the list. To modify a list as you work through it, use a while loop. Using while loops with lists and dictionaries allows you to collect, store, and organize lots of input to examine and report on later. Moving Items from One List to Another Consider a list of newly registered but unverified users of a website. After we verify these users, how can we move them to a separate list of confirmed users? One way would be to use a while loop to pull users from the list of unconfirmed users as we verify them and then add them to a separate list of confirmed users. Here’s what that code might look like: confirmed_ # Start with users that need to be verified, users.py # and an empty list to hold confirmed users. u unconfirmed_users = ['alice', 'brian', 'candace'] confirmed_users = [] # Verify each user until there are no more unconfirmed users. # Move each verified user into the list of confirmed users. v while unconfirmed_users: w current_user = unconfirmed_users.pop() print("Verifying user: " + current_user.title()) x confirmed_users.append(current_user)

User Input and while Loops 129 # Display all confirmed users. print("\nThe following users have been confirmed:") for confirmed_user in confirmed_users: print(confirmed_user.title()) We begin with a list of unconfirmed users at u (Alice, Brian, and Candace) and an empty list to hold confirmed users. The while loop at v runs as long as the list unconfirmed_users is not empty. Within this loop, the pop() function at w removes unverified users one at a time from the end of unconfirmed_users. Here, because Candace is last in the unconfirmed_users list, her name will be the first to be removed, stored in current_user, and added to the confirmed_users list at x. Next is Brian, then Alice. We simulate confirming each user by printing a verification message and then adding them to the list of confirmed users. As the list of uncon- firmed users shrinks, the list of confirmed users grows. When the list of unconfirmed users is empty, the loop stops and the list of confirmed users is printed: Verifying user: Candace Verifying user: Brian Verifying user: Alice The following users have been confirmed: Candace Brian Alice Removing All Instances of Specific Values from a List In Chapter 3 we used remove() to remove a specific value from a list. The remove() function worked because the value we were interested in appeared only once in the list. But what if you want to remove all instances of a value from a list? Say you have a list of pets with the value 'cat' repeated several times. To remove all instances of that value, you can run a while loop until 'cat' is no longer in the list, as shown here: pets.py pets = ['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat'] print(pets) while 'cat' in pets: pets.remove('cat') print(pets) We start with a list containing multiple instances of 'cat'. After printing the list, Python enters the while loop because it finds the value 'cat' in the list

130 Chapter 7 at least once. Once inside the loop, Python removes the first instance of 'cat', returns to the while line, and then reenters the loop when it finds that 'cat' is still in the list. It removes each instance of 'cat' until the value is no longer in the list, at which point Python exits the loop and prints the list again: ['dog', 'cat', 'dog', 'goldfish', 'cat', 'rabbit', 'cat'] ['dog', 'dog', 'goldfish', 'rabbit'] Filling a Dictionary with User Input You can prompt for as much input as you need in each pass through a while loop. Let’s make a polling program in which each pass through the loop prompts for the participant’s name and response. We’ll store the data we gather in a dictionary, because we want to connect each response with a particular user: mountain_ responses = {} poll.py # Set a flag to indicate that polling is active. polling_active = True while polling_active: # Prompt for the person's name and response. u name = input("\nWhat is your name? ") response = input("Which mountain would you like to climb someday? ") # Store the response in the dictionary: v responses[name] = response # Find out if anyone else is going to take the poll. w repeat = input("Would you like to let another person respond? (yes/ no) ") if repeat == 'no': polling_active = False # Polling is complete. Show the results. print("\n--- Poll Results ---") x for name, response in responses.items(): print(name + " would like to climb " + response + ".") The program first defines an empty dictionary (responses) and sets a flag (polling_active) to indicate that polling is active. As long as polling_active is True, Python will run the code in the while loop. Within the loop, the user is prompted to enter their username and a mountain they’d like to climb u. That information is stored in the responses dictionary v, and the user is asked whether or not to keep the poll run- ning w. If they enter yes, the program enters the while loop again. If they enter no, the polling_active flag is set to False, the while loop stops running, and the final code block at x displays the results of the poll.

User Input and while Loops 131 If you run this program and enter sample responses, you should see output like this: What is your name? Eric Which mountain would you like to climb someday? Denali Would you like to let another person respond? (yes/ no) yes What is your name? Lynn Which mountain would you like to climb someday? Devil's Thumb Would you like to let another person respond? (yes/ no) no --- Poll Results --- Lynn would like to climb Devil's Thumb. Eric would like to climb Denali. try It yourse lf 7-8. Deli: Make a list called sandwich_orders and fill it with the names of vari- ous sandwiches Then make an empty list called finished_sandwiches Loop through the list of sandwich orders and print a message for each order, such as I made your tuna sandwich. As each sandwich is made, move it to the list of finished sandwiches After all the sandwiches have been made, print a message listing each sandwich that was made 7-9. No Pastrami: Using the list sandwich_orders from Exercise 7-8, make sure the sandwich 'pastrami' appears in the list at least three times Add code near the beginning of your program to print a message saying the deli has run out of pastrami, and then use a while loop to remove all occurrences of 'pastrami' from sandwich_orders Make sure no pastrami sandwiches end up in finished_sandwiches 7-10. Dream Vacation: Write a program that polls users about their dream vacation Write a prompt similar to If you could visit one place in the world, where would you go? Include a block of code that prints the results of the poll summary In this chapter you learned how to use input() to allow users to provide their own information in your programs. You learned to work with both text and numerical input and how to use while loops to make your programs run as long as your users want them to. You saw several ways to control the flow of a while loop by setting an active flag, using the break statement, and

132 Chapter 7 using the continue statement. You learned how to use a while loop to move items from one list to another and how to remove all instances of a value from a list. You also learned how while loops can be used with dictionaries. In Chapter 8 you’ll learn about functions. Functions allow you to break your programs into small parts, each of which does one specific job. You can call a function as many times as you want, and you can store your functions in separate files. By using functions, you’ll be able to write more efficient code that’s easier to troubleshoot and maintain and that can be reused in many different programs.

8f u n C t I o n s In this chapter you’ll learn to write functions, which are named blocks of code that are designed to do one specific job. When you want to perform a particular task that you’ve defined in a function, you call the name of the function responsible for it. If you need to perform that task multiple times throughout your program, you don’t need to type all the code for the same task again and again; you just call the function dedicated to handling that task, and the call tells Python to run the code inside the function. You’ll find that using functions makes your programs easier to write, read, test, and fix. In this chapter you’ll also learn ways to pass information to functions. You’ll learn how to write certain functions whose primary job is to display information and other functions designed to process data and return a value or set of values. Finally, you’ll learn to store functions in separate files called modules to help organize your main program files.

134 Chapter 8 defining a function Here’s a simple function named greet_user() that prints a greeting: greeter.py u def greet_user(): v """Display a simple greeting.""" w print("Hello!") x greet_user() This example shows the simplest structure of a function. The line at u uses the keyword def to inform Python that you’re defining a function. This is the function definition, which tells Python the name of the function and, if applicable, what kind of information the function needs to do its job. The parentheses hold that information. In this case, the name of the function is greet_user(), and it needs no information to do its job, so its parentheses are empty. (Even so, the parentheses are required.) Finally, the definition ends in a colon. Any indented lines that follow def greet_user(): make up the body of the function. The text at v is a comment called a docstring, which describes what the function does. Docstrings are enclosed in triple quotes, which Python looks for when it generates documentation for the functions in your programs. The line print("Hello!") w is the only line of actual code in the body of this function, so greet_user() has just one job: print("Hello!"). When you want to use this function, you call it. A function call tells Python to execute the code in the function. To call a function, you write the name of the function, followed by any necessary information in paren- theses, as shown at x. Because no information is needed here, calling our function is as simple as entering greet_user(). As expected, it prints Hello!: Hello! Passing Information to a Function Modified slightly, the function greet_user() can not only tell the user Hello! but also greet them by name. For the function to do this, you enter username in the parentheses of the function’s definition at def greet_user(). By add- ing username here you allow the function to accept any value of username you specify. The function now expects you to provide a value for username each time you call it. When you call greet_user(), you can pass it a name, such as 'jesse', inside the parentheses: def greet_user(username): """Display a simple greeting.""" print("Hello, " + username.title() + "!") greet_user('jesse')

Functions 135 Entering greet_user('jesse') calls greet_user() and gives the function the information it needs to execute the print statement. The function accepts the name you passed it and displays the greeting for that name: Hello, Jesse! Likewise, entering greet_user('sarah') calls greet_user(), passes it 'sarah', and prints Hello, Sarah! You can call greet_user() as often as you want and pass it any name you want to produce a predictable output every time. Arguments and Parameters In the preceding greet_user() function, we defined greet_user() to require a value for the variable username. Once we called the function and gave it the information (a person’s name), it printed the right greeting. The variable username in the definition of greet_user() is an example of a parameter, a piece of information the function needs to do its job. The value 'jesse' in greet_user('jesse') is an example of an argument. An argument is a piece of information that is passed from a function call to a function. When we call the function, we place the value we want the function to work with in parentheses. In this case the argument 'jesse' was passed to the function greet_user(), and the value was stored in the parameter username. n o t e People sometimes speak of arguments and parameters interchangeably. Don’t be sur- prised if you see the variables in a function definition referred to as arguments or the variables in a function call referred to as parameters. try It yourse lf 8-1. Message: Write a function called display_message() that prints one sen- tence telling everyone what you are learning about in this chapter Call the function, and make sure the message displays correctly 8-2. Favorite Book: Write a function called favorite_book() that accepts one parameter, title The function should print a message, such as One of my favorite books is Alice in Wonderland Call the function, making sure to include a book title as an argument in the function call Passing arguments Because a function definition can have multiple parameters, a function call may need multiple arguments. You can pass arguments to your functions in a number of ways. You can use positional arguments, which need to be in

136 Chapter 8 the same order the parameters were written; keyword arguments, where each argument consists of a variable name and a value; and lists and dictionaries of values. Let’s look at each of these in turn. Positional Arguments When you call a function, Python must match each argument in the func- tion call with a parameter in the function definition. The simplest way to do this is based on the order of the arguments provided. Values matched up this way are called positional arguments. To see how this works, consider a function that displays information about pets. The function tells us what kind of animal each pet is and the pet’s name, as shown here: pets.py u def describe_pet(animal_type, pet_name): """Display information about a pet.""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name.title() + ".") v describe_pet('hamster', 'harry') The definition shows that this function needs a type of animal and the animal’s name u. When we call describe_pet(), we need to provide an ani- mal type and a name, in that order. For example, in the function call, the argument 'hamster' is stored in the parameter animal_type and the argu- ment 'harry' is stored in the parameter pet_name v. In the function body, these two parameters are used to display information about the pet being described. The output describes a hamster named Harry: I have a hamster. My hamster's name is Harry. Multiple Function Calls You can call a function as many times as needed. Describing a second, dif- ferent pet requires just one more call to describe_pet(): def describe_pet(animal_type, pet_name): """Display information about a pet.""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name.title() + ".") describe_pet('hamster', 'harry') describe_pet('dog', 'willie') In this second function call, we pass describe_pet() the arguments 'dog' and 'willie'. As with the previous set of arguments we used, Python matches 'dog' with the parameter animal_type and 'willie' with the parameter pet_name.

Functions 137 As before, the function does its job, but this time it prints values for a dog named Willie. Now we have a hamster named Harry and a dog named Willie: I have a hamster. My hamster's name is Harry. I have a dog. My dog's name is Willie. Calling a function multiple times is a very efficient way to work. The code describing a pet is written once in the function. Then, anytime you want to describe a new pet, you call the function with the new pet’s infor- mation. Even if the code for describing a pet were to expand to ten lines, you could still describe a new pet in just one line by calling the function again. You can use as many positional arguments as you need in your func- tions. Python works through the arguments you provide when calling the function and matches each one with the corresponding parameter in the function’s definition. Order Matters in Positional arguments You can get unexpected results if you mix up the order of the arguments in a function call when using positional arguments: def describe_pet(animal_type, pet_name): """Display information about a pet.""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name.title() + ".") describe_pet('harry', 'hamster') In this function call we list the name first and the type of animal second. Because the argument 'harry' is listed first this time, that value is stored in the parameter animal_type. Likewise, 'hamster' is stored in pet_name. Now we have a “harry” named “Hamster”: I have a harry. My harry's name is Hamster. If you get funny results like this, check to make sure the order of the arguments in your function call matches the order of the parameters in the function’s definition. Keyword Arguments A keyword argument is a name-value pair that you pass to a function. You directly associate the name and the value within the argument, so when you pass the argument to the function, there’s no confusion (you won’t end up

138 Chapter 8 with a harry named Hamster). Keyword arguments free you from having to worry about correctly ordering your arguments in the function call, and they clarify the role of each value in the function call. Let’s rewrite pets.py using keyword arguments to call describe_pet(): def describe_pet(animal_type, pet_name): """Display information about a pet.""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name.title() + ".") describe_pet(animal_type='hamster', pet_name='harry') The function describe_pet() hasn’t changed. But when we call the func- tion, we explicitly tell Python which parameter each argument should be matched with. When Python reads the function call, it knows to store the argument 'hamster' in the parameter animal_type and the argument 'harry' in pet_name. The output correctly shows that we have a hamster named Harry. The order of keyword arguments doesn’t matter because Python knows where each value should go. The following two function calls are equivalent: describe_pet(animal_type='hamster', pet_name='harry') describe_pet(pet_name='harry', animal_type='hamster') n o t e When you use keyword arguments, be sure to use the exact names of the parameters in the function’s definition. Default Values When writing a function, you can define a default value for each parameter. If an argument for a parameter is provided in the function call, Python uses the argument value. If not, it uses the parameter’s default value. So when you define a default value for a parameter, you can exclude the correspond- ing argument you’d usually write in the function call. Using default values can simplify your function calls and clarify the ways in which your functions are typically used. For example, if you notice that most of the calls to describe_pet() are being used to describe dogs, you can set the default value of animal_type to 'dog'. Now anyone calling describe_pet() for a dog can omit that information: def describe_pet(pet_name, animal_type='dog'): """Display information about a pet.""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name.title() + ".") describe_pet(pet_name='willie')

Functions 139 We changed the definition of describe_pet() to include a default value, 'dog', for animal_type. Now when the function is called with no animal_type specified, Python knows to use the value 'dog' for this parameter: I have a dog. My dog's name is Willie. Note that the order of the parameters in the function definition had to be changed. Because the default value makes it unnecessary to specify a type of animal as an argument, the only argument left in the function call is the pet’s name. Python still interprets this as a positional argument, so if the function is called with just a pet’s name, that argument will match up with the first parameter listed in the function’s definition. This is the rea- son the first parameter needs to be pet_name. The simplest way to use this function now is to provide just a dog’s name in the function call: describe_pet('willie') This function call would have the same output as the previous example. The only argument provided is 'willie', so it is matched up with the first parameter in the definition, pet_name. Because no argument is provided for animal_type, Python uses the default value 'dog'. To describe an animal other than a dog, you could use a function call like this: describe_pet(pet_name='harry', animal_type='hamster') Because an explicit argument for animal_type is provided, Python will ignore the parameter’s default value. n o t e When you use default values, any parameter with a default value needs to be listed after all the parameters that don’t have default values. This allows Python to con- tinue interpreting positional arguments correctly. Equivalent Function Calls Because positional arguments, keyword arguments, and default values can all be used together, often you’ll have several equivalent ways to call a func- tion. Consider the following definition for describe_pets() with one default value provided: def describe_pet(pet_name, animal_type='dog'): With this definition, an argument always needs to be provided for pet_name, and this value can be provided using the positional or keyword

140 Chapter 8 format. If the animal being described is not a dog, an argument for animal_type must be included in the call, and this argument can also be specified using the positional or keyword format. All of the following calls would work for this function: # A dog named Willie. describe_pet('willie') describe_pet(pet_name='willie') # A hamster named Harry. describe_pet('harry', 'hamster') describe_pet(pet_name='harry', animal_type='hamster') describe_pet(animal_type='hamster', pet_name='harry') Each of these function calls would have the same output as the previous examples. n o t e It doesn’t really matter which calling style you use. As long as your function calls pro- duce the output you want, just use the style you find easiest to understand. Avoiding Argument Errors When you start to use functions, don’t be surprised if you encounter errors about unmatched arguments. Unmatched arguments occur when you provide fewer or more arguments than a function needs to do its work. For example, here’s what happens if we try to call describe_pet() with no arguments: def describe_pet(animal_type, pet_name): """Display information about a pet.""" print("\nI have a " + animal_type + ".") print("My " + animal_type + "'s name is " + pet_name.title() + ".") describe_pet() Python recognizes that some information is missing from the function call, and the traceback tells us that: Traceback (most recent call last): u File "pets.py", line 6, in <module> v describe_pet() w TypeError: describe_pet() missing 2 required positional arguments: 'animal_ type' and 'pet_name' At u the traceback tells us the location of the problem, allowing us to look back and see that something went wrong in our function call. At v the offending function call is written out for us to see. At w the traceback

Functions 141 tells us the call is missing two arguments and reports the names of the miss- ing arguments. If this function were in a separate file, we could probably rewrite the call correctly without having to open that file and read the func- tion code. Python is helpful in that it reads the function’s code for us and tells us the names of the arguments we need to provide. This is another motiva- tion for giving your variables and functions descriptive names. If you do, Python’s error messages will be more useful to you and anyone else who might use your code. If you provide too many arguments, you should get a similar trace- back that can help you correctly match your function call to the function definition. try It yourse lf 8-3. T-Shirt: Write a function called make_shirt() that accepts a size and the text of a message that should be printed on the shirt The function should print a sentence summarizing the size of the shirt and the message printed on it Call the function once using positional arguments to make a shirt Call the function a second time using keyword arguments 8-4. Large Shirts: Modify the make_shirt() function so that shirts are large by default with a message that reads I love Python Make a large shirt and a medium shirt with the default message, and a shirt of any size with a different message 8-5. Cities: Write a function called describe_city() that accepts the name of a city and its country The function should print a simple sentence, such as Reykjavik is in Iceland Give the parameter for the country a default value Call your function for three different cities, at least one of which is not in the default country return Values A function doesn’t always have to display its output directly. Instead, it can process some data and then return a value or set of values. The value the function returns is called a return value. The return statement takes a value from inside a function and sends it back to the line that called the function. Return values allow you to move much of your program’s grunt work into functions, which can simplify the body of your program.

142 Chapter 8 Returning a Simple Value Let’s look at a function that takes a first and last name, and returns a neatly formatted full name: formatted_ u def get_formatted_name(first_name, last_name): name.py """Return a full name, neatly formatted.""" v full_name = first_name + ' ' + last_name w return full_name.title() x musician = get_formatted_name('jimi', 'hendrix') print(musician) The definition of get_formatted_name() takes as parameters a first and last name u. The function combines these two names, adds a space between them, and stores the result in full_name v. The value of full_name is con- verted to title case, and then returned to the calling line at w. When you call a function that returns a value, you need to provide a variable where the return value can be stored. In this case, the returned value is stored in the variable musician at x. The output shows a neatly for- matted name made up of the parts of a person’s name: Jimi Hendrix This might seem like a lot of work to get a neatly formatted name when we could have just written: print("Jimi Hendrix") But when you consider working with a large program that needs to store many first and last names separately, functions like get_formatted_name() become very useful. You store first and last names separately and then call this function whenever you want to display a full name. Making an Argument Optional Sometimes it makes sense to make an argument optional so that people using the function can choose to provide extra information only if they want to. You can use default values to make an argument optional. For example, say we want to expand get_formatted_name() to handle middle names as well. A first attempt to include middle names might look like this: def get_formatted_name(first_name, middle_name, last_name): """Return a full name, neatly formatted.""" full_name = first_name + ' ' + middle_name + ' ' + last_name return full_name.title() musician = get_formatted_name('john', 'lee', 'hooker') print(musician)

Functions 143 This function works when given a first, middle, and last name. The function takes in all three parts of a name and then builds a string out of them. The function adds spaces where appropriate and converts the full name to title case: John Lee Hooker But middle names aren’t always needed, and this function as written would not work if you tried to call it with only a first name and a last name. To make the middle name optional, we can give the middle_name argument an empty default value and ignore the argument unless the user provides a value. To make get_formatted_name() work without a middle name, we set the default value of middle_name to an empty string and move it to the end of the list of parameters: u def get_formatted_name(first_name, last_name, middle_name=''): """Return a full name, neatly formatted.""" v if middle_name: full_name = first_name + ' ' + middle_name + ' ' + last_name w else: full_name = first_name + ' ' + last_name return full_name.title() musician = get_formatted_name('jimi', 'hendrix') print(musician) x musician = get_formatted_name('john', 'hooker', 'lee') print(musician) In this example, the name is built from three possible parts. Because there’s always a first and last name, these parameters are listed first in the function’s definition. The middle name is optional, so it’s listed last in the definition, and its default value is an empty string u. In the body of the function, we check to see if a middle name has been provided. Python interprets non-empty strings as True, so if middle_name evaluates to True if a middle name argument is in the function call v. If a middle name is provided, the first, middle, and last names are combined to form a full name. This name is then changed to title case and returned to the function call line where it’s stored in the variable musician and printed. If no middle name is provided, the empty string fails the if test and the else block runs w. The full name is made with just a first and last name, and the formatted name is returned to the calling line where it’s stored in musician and printed. Calling this function with a first and last name is straightforward. If we’re using a middle name, however, we have to make sure the middle name is the last argument passed so Python will match up the positional arguments correctly x.

144 Chapter 8 This modified version of our function works for people with just a first and last name, and it works for people who have a middle name as well: Jimi Hendrix John Lee Hooker Optional values allow functions to handle a wide range of use cases while letting function calls remain as simple as possible. Returning a Dictionary A function can return any kind of value you need it to, including more com- plicated data structures like lists and dictionaries. For example, the follow- ing function takes in parts of a name and returns a dictionary representing a person: person.py def build_person(first_name, last_name): """Return a dictionary of information about a person.""" u person = {'first': first_name, 'last': last_name} v return person musician = build_person('jimi', 'hendrix') w print(musician) The function build_person() takes in a first and last name, and packs these values into a dictionary at u. The value of first_name is stored with the key 'first', and the value of last_name is stored with the key 'last'. The entire dictionary representing the person is returned at v. The return value is printed at w with the original two pieces of textual information now stored in a dictionary: {'first': 'jimi', 'last': 'hendrix'} This function takes in simple textual information and puts it into a more meaningful data structure that lets you work with the information beyond just printing it. The strings 'jimi' and 'hendrix' are now labeled as a first name and last name. You can easily extend this function to accept optional values like a middle name, an age, an occupation, or any other information you want to store about a person. For example, the following change allows you to store a person’s age as well: def build_person(first_name, last_name, age=''): """Return a dictionary of information about a person.""" person = {'first': first_name, 'last': last_name} if age: person['age'] = age return person musician = build_person('jimi', 'hendrix', age=27) print(musician)

Functions 145 We add a new optional parameter age to the function definition and assign the parameter an empty default value. If the function call includes a value for this parameter, the value is stored in the dictionary. This function always stores a person’s name, but it can also be modified to store any other information you want about a person. Using a Function with a while Loop You can use functions with all the Python structures you’ve learned about so far. For example, let’s use the get_formatted_name() function with a while loop to greet users more formally. Here’s a first attempt at greeting people using their first and last names: greeter.py def get_formatted_name(first_name, last_name): """Return a full name, neatly formatted.""" full_name = first_name + ' ' + last_name return full_name.title() # This is an infinite loop! while True: u print("\nPlease tell me your name:") f_name = input("First name: ") l_name = input("Last name: ") formatted_name = get_formatted_name(f_name, l_name) print("\nHello, " + formatted_name + "!") For this example, we use a simple version of get_formatted_name() that doesn’t involve middle names. The while loop asks the user to enter their name, and we prompt for their first and last name separately u. But there’s one problem with this while loop: We haven’t defined a quit condition. Where do you put a quit condition when you ask for a series of inputs? We want the user to be able to quit as easily as possible, so each prompt should offer a way to quit. The break statement offers a straight- forward way to exit the loop at either prompt: def get_formatted_name(first_name, last_name): """Return a full name, neatly formatted.""" full_name = first_name + ' ' + last_name return full_name.title() while True: print("\nPlease tell me your name:") print("(enter 'q' at any time to quit)") f_name = input("First name: ") if f_name == 'q': break l_name = input("Last name: ") if l_name == 'q': break

146 Chapter 8 formatted_name = get_formatted_name(f_name, l_name) print("\nHello, " + formatted_name + "!") We add a message that informs the user how to quit, and then we break out of the loop if the user enters the quit value at either prompt. Now the program will continue greeting people until someone enters 'q' for either name: Please tell me your name: (enter 'q' at any time to quit) First name: eric Last name: matthes Hello, Eric Matthes! Please tell me your name: (enter 'q' at any time to quit) First name: q try It yourse lf 8-6. City Names: Write a function called city_country() that takes in the name of a city and its country The function should return a string formatted like this: "Santiago, Chile" Call your function with at least three city-country pairs, and print the value that’s returned 8-7. Album: Write a function called make_album() that builds a dictionary describing a music album The function should take in an artist name and an album title, and it should return a dictionary containing these two pieces of information Use the function to make three dictionaries representing different albums Print each return value to show that the dictionaries are storing the album information correctly Add an optional parameter to make_album() that allows you to store the number of tracks on an album If the calling line includes a value for the num- ber of tracks, add that value to the album’s dictionary Make at least one new function call that includes the number of tracks on an album 8-8. User Albums: Start with your program from Exercise 8-7 Write a while loop that allows users to enter an album’s artist and title Once you have that information, call make_album() with the user’s input and print the dictionary that’s created Be sure to include a quit value in the while loop

Functions 147 Passing a list You’ll often find it useful to pass a list to a function, whether it’s a list of names, numbers, or more complex objects, such as dictionaries. When you pass a list to a function, the function gets direct access to the contents of the list. Let’s use functions to make working with lists more efficient. Say we have a list of users and want to print a greeting to each. The following example sends a list of names to a function called greet_users(), which greets each person in the list individually: greet_users.py def greet_users(names): """Print a simple greeting to each user in the list.""" for name in names: msg = "Hello, " + name.title() + "!" print(msg) u usernames = ['hannah', 'ty', 'margot'] greet_users(usernames) We define greet_users() so it expects a list of names, which it stores in the parameter names. The function loops through the list it receives and prints a greeting to each user. At u we define a list of users and then pass the list usernames to greet_users()in our function call: Hello, Hannah! Hello, Ty! Hello, Margot! This is the output we wanted. Every user sees a personalized greet- ing, and you can call the function any time you want to greet a specific set of users. Modifying a List in a Function When you pass a list to a function, the function can modify the list. Any changes made to the list inside the function’s body are permanent, allowing you to work efficiently even when you’re dealing with large amounts of data. Consider a company that creates 3D printed models of designs that users submit. Designs that need to be printed are stored in a list, and after being printed they’re moved to a separate list. The following code does this without using functions: printing_ # Start with some designs that need to be printed. models.py unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron'] completed_models = [] # Simulate printing each design, until none are left. # Move each design to completed_models after printing. while unprinted_designs: current_design = unprinted_designs.pop()

148 Chapter 8 # Simulate creating a 3D print from the design. print("Printing model: " + current_design) completed_models.append(current_design) # Display all completed models. print("\nThe following models have been printed:") for completed_model in completed_models: print(completed_model) This program starts with a list of designs that need to be printed and an empty list called completed_models that each design will be moved to after it has been printed. As long as designs remain in unprinted_designs, the while loop simulates printing each design by removing a design from the end of the list, storing it in current_design, and displaying a message that the cur- rent design is being printed. It then adds the design to the list of completed models. When the loop is finished running, a list of the designs that have been printed is displayed: Printing model: dodecahedron Printing model: robot pendant Printing model: iphone case The following models have been printed: dodecahedron robot pendant iphone case We can reorganize this code by writing two functions, each of which does one specific job. Most of the code won’t change; we’re just making it more efficient. The first function will handle printing the designs, and the second will summarize the prints that have been made: u def print_models(unprinted_designs, completed_models): """ Simulate printing each design, until none are left. Move each design to completed_models after printing. """ while unprinted_designs: current_design = unprinted_designs.pop() # Simulate creating a 3D print from the design. print("Printing model: " + current_design) completed_models.append(current_design) v def show_completed_models(completed_models): """Show all the models that were printed.""" print("\nThe following models have been printed:") for completed_model in completed_models: print(completed_model) unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron'] completed_models = []

Functions 149 print_models(unprinted_designs, completed_models) show_completed_models(completed_models) At u we define the function print_models() with two parameters: a list of designs that need to be printed and a list of completed models. Given these two lists, the function simulates printing each design by emptying the list of unprinted designs and filling up the list of completed models. At v we define the function show_completed_models() with one parameter: the list of completed models. Given this list, show_completed_models() displays the name of each model that was printed. This program has the same output as the version without functions, but the code is much more organized. The code that does most of the work has been moved to two separate functions, which makes the main part of the program easier to understand. Look at the body of the program to see how much easier it is to understand what this program is doing: unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron'] completed_models = [] print_models(unprinted_designs, completed_models) show_completed_models(completed_models) We set up a list of unprinted designs and an empty list that will hold the completed models. Then, because we’ve already defined our two functions, all we have to do is call them and pass them the right arguments. We call print_models() and pass it the two lists it needs; as expected, print_models() simulates printing the designs. Then we call show_completed_models() and pass it the list of completed models so it can report the models that have been printed. The descriptive function names allow others to read this code and understand it, even without comments. This program is easier to extend and maintain than the version with- out functions. If we need to print more designs later on, we can simply call print_models() again. If we realize the printing code needs to be modified, we can change the code once, and our changes will take place everywhere the function is called. This technique is more efficient than having to update code separately in several places in the program. This example also demonstrates the idea that every function should have one specific job. The first function prints each design, and the second displays the completed models. This is more beneficial than using one func- tion to do both jobs. If you’re writing a function and notice the function is doing too many different tasks, try to split the code into two functions. Remember that you can always call a function from another function, which can be helpful when splitting a complex task into a series of steps. Preventing a Function from Modifying a List Sometimes you’ll want to prevent a function from modifying a list. For example, say that you start with a list of unprinted designs and write a

150 Chapter 8 function to move them to a list of completed models, as in the previous example. You may decide that even though you’ve printed all the designs, you want to keep the original list of unprinted designs for your records. But because you moved all the design names out of unprinted_designs, the list is now empty, and the empty list is the only version you have; the original is gone. In this case, you can address this issue by passing the function a copy of the list, not the original. Any changes the function makes to the list will affect only the copy, leaving the original list intact. You can send a copy of a list to a function like this: function_name(list_name[:]) The slice notation [:] makes a copy of the list to send to the function. If we didn’t want to empty the list of unprinted designs in print_models.py, we could call print_models() like this: print_models(unprinted_designs[:], completed_models) The function print_models() can do its work because it still receives the names of all unprinted designs. But this time it uses a copy of the origi- nal unprinted designs list, not the actual unprinted_designs list. The list completed_models will fill up with the names of printed models like it did before, but the original list of unprinted designs will be unaffected by the function. Even though you can preserve the contents of a list by passing a copy of it to your functions, you should pass the original list to functions unless you have a specific reason to pass a copy. It’s more efficient for a function to work with an existing list to avoid using the time and memory needed to make a separate copy, especially when you’re working with large lists. try It yourse lf 8-9. Magicians: Make a list of magician’s names Pass the list to a function called show_magicians(), which prints the name of each magician in the list 8-10. Great Magicians: Start with a copy of your program from Exercise 8-9 Write a function called make_great() that modifies the list of magicians by add- ing the phrase the Great to each magician’s name Call show_magicians() to see that the list has actually been modified 8-11. Unchanged Magicians: Start with your work from Exercise 8-10 Call the function make_great() with a copy of the list of magicians’ names Because the original list will be unchanged, return the new list and store it in a separate list Call show_magicians() with each list to show that you have one list of the origi- nal names and one list with the Great added to each magician’s name

Functions 151 Passing an arbitrary number of arguments Sometimes you won’t know ahead of time how many arguments a function needs to accept. Fortunately, Python allows a function to collect an arbi- trary number of arguments from the calling statement. For example, consider a function that builds a pizza. It needs to accept a number of toppings, but you can’t know ahead of time how many toppings a person will want. The function in the following example has one param- eter, *toppings, but this parameter collects as many arguments as the calling line provides: pizza.py def make_pizza(*toppings): """Print the list of toppings that have been requested.""" print(toppings) make_pizza('pepperoni') make_pizza('mushrooms', 'green peppers', 'extra cheese') The asterisk in the parameter name *toppings tells Python to make an empty tuple called toppings and pack whatever values it receives into this tuple. The print statement in the function body produces output showing that Python can handle a function call with one value and a call with three values. It treats the different calls similarly. Note that Python packs the arguments into a tuple, even if the function receives only one value: ('pepperoni',) ('mushrooms', 'green peppers', 'extra cheese') Now we can replace the print statement with a loop that runs through the list of toppings and describes the pizza being ordered: def make_pizza(*toppings): """Summarize the pizza we are about to make.""" print("\nMaking a pizza with the following toppings:") for topping in toppings: print("- " + topping) make_pizza('pepperoni') make_pizza('mushrooms', 'green peppers', 'extra cheese') The function responds appropriately, whether it receives one value or three values: Making a pizza with the following toppings: - pepperoni Making a pizza with the following toppings: - mushrooms - green peppers - extra cheese

152 Chapter 8 This syntax works no matter how many arguments the function receives. Mixing Positional and Arbitrary Arguments If you want a function to accept several different kinds of arguments, the parameter that accepts an arbitrary number of arguments must be placed last in the function definition. Python matches positional and keyword arguments first and then collects any remaining arguments in the final parameter. For example, if the function needs to take in a size for the pizza, that parameter must come before the parameter *toppings: def make_pizza(size, *toppings): """Summarize the pizza we are about to make.""" print("\nMaking a " + str(size) + "-inch pizza with the following toppings:") for topping in toppings: print("- " + topping) make_pizza(16, 'pepperoni') make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese') In the function definition, Python stores the first value it receives in the parameter size. All other values that come after are stored in the tuple toppings. The function calls include an argument for the size first, followed by as many toppings as needed. Now each pizza has a size and a number of toppings, and each piece of information is printed in the proper place, showing size first and toppings after: Making a 16-inch pizza with the following toppings: - pepperoni Making a 12-inch pizza with the following toppings: - mushrooms - green peppers - extra cheese Using Arbitrary Keyword Arguments Sometimes you’ll want to accept an arbitrary number of arguments, but you won’t know ahead of time what kind of information will be passed to the function. In this case, you can write functions that accept as many key-value pairs as the calling statement provides. One example involves building user profiles: you know you’ll get information about a user, but you’re not sure what kind of information you’ll receive. The function build_profile() in the

Functions 153 following example always takes in a first and last name, but it accepts an arbitrary number of keyword arguments as well: user_profile.py def build_profile(first, last, **user_info): """Build a dictionary containing everything we know about a user.""" profile = {} u profile['first_name'] = first profile['last_name'] = last v for key, value in user_info.items(): profile[key] = value return profile user_profile = build_profile('albert', 'einstein', location='princeton', field='physics') print(user_profile) The definition of build_profile() expects a first and last name, and then it allows the user to pass in as many name-value pairs as they want. The double asterisks before the parameter **user_info cause Python to create an empty dictionary called user_info and pack whatever name-value pairs it receives into this dictionary. Within the function, you can access the name- value pairs in user_info just as you would for any dictionary. In the body of build_profile(), we make an empty dictionary called profile to hold the user’s profile. At u we add the first and last names to this dictionary because we’ll always receive these two pieces of information from the user. At v we loop through the additional key-value pairs in the dictionary user_info and add each pair to the profile dictionary. Finally, we return the profile dictionary to the function call line. We call build_profile(), passing it the first name 'albert', the last name 'einstein', and the two key-value pairs location='princeton' and field='physics'. We store the returned profile in user_profile and print user_profile: {'first_name': 'albert', 'last_name': 'einstein', 'location': 'princeton', 'field': 'physics'} The returned dictionary contains the user’s first and last names and, in this case, the location and field of study as well. The function would work no matter how many additional key-value pairs are provided in the function call. You can mix positional, keyword, and arbitrary values in many dif- ferent ways when writing your own functions. It’s useful to know that all these argument types exist because you’ll see them often when you start reading other people’s code. It takes practice to learn to use the different types correctly and to know when to use each type. For now, remember to use the simplest approach that gets the job done. As you progress you’ll learn to use the most efficient approach each time.

154 Chapter 8 try It yourse lf 8-12. Sandwiches: Write a function that accepts a list of items a person wants on a sandwich The function should have one parameter that collects as many items as the function call provides, and it should print a summary of the sand- wich that is being ordered Call the function three times, using a different num- ber of arguments each time 8-13. User Profile: Start with a copy of user_profile.py from page 153 Build a profile of yourself by calling build_profile(), using your first and last names and three other key-value pairs that describe you 8-14. Cars: Write a function that stores information about a car in a diction- ary The function should always receive a manufacturer and a model name It should then accept an arbitrary number of keyword arguments Call the func- tion with the required information and two other name-value pairs, such as a color or an optional feature Your function should work for a call like this one: car = make_car('subaru', 'outback', color='blue', tow_package=True) Print the dictionary that’s returned to make sure all the information was stored correctly storing your functions in modules One advantage of functions is the way they separate blocks of code from your main program. By using descriptive names for your functions, your main program will be much easier to follow. You can go a step further by storing your functions in a separate file called a module and then importing that module into your main program. An import statement tells Python to make the code in a module available in the currently running program file. Storing your functions in a separate file allows you to hide the details of your program’s code and focus on its higher-level logic. It also allows you to reuse functions in many different programs. When you store your functions in separate files, you can share those files with other programmers without having to share your entire program. Knowing how to import functions also allows you to use libraries of functions that other programmers have written. There are several ways to import a module, and I’ll show you each of these briefly. Importing an Entire Module To start importing functions, we first need to create a module. A module is a file ending in .py that contains the code you want to import into your

Functions 155 program. Let’s make a module that contains the function make_pizza(). To make this module, we’ll remove everything from the file pizza.py except the function make_pizza(): pizza.py def make_pizza(size, *toppings): """Summarize the pizza we are about to make.""" print("\nMaking a " + str(size) + "-inch pizza with the following toppings:") for topping in toppings: print("- " + topping) Now we’ll make a separate file called making_pizzas.py in the same directory as pizza.py. This file imports the module we just created and then makes two calls to make_pizza(): making_ import pizza pizzas.py u pizza.make_pizza(16, 'pepperoni') pizza.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese') When Python reads this file, the line import pizza tells Python to open the file pizza.py and copy all the functions from it into this program. You don’t actually see code being copied between files because Python copies the code behind the scenes as the program runs. All you need to know is that any function defined in pizza.py will now be available in making_pizzas.py. To call a function from an imported module, enter the name of the module you imported, pizza, followed by the name of the function, make_pizza(), separated by a dot u. This code produces the same output as the original program that didn’t import a module: Making a 16-inch pizza with the following toppings: - pepperoni Making a 12-inch pizza with the following toppings: - mushrooms - green peppers - extra cheese This first approach to importing, in which you simply write import fol- lowed by the name of the module, makes every function from the module available in your program. If you use this kind of import statement to import an entire module named module_name.py, each function in the module is available through the following syntax: module_name.function_name()

156 Chapter 8 Importing Specific Functions You can also import a specific function from a module. Here’s the general syntax for this approach: from module_name import function_name You can import as many functions as you want from a module by sepa- rating each function’s name with a comma: from module_name import function_0, function_1, function_2 The making_pizzas.py example would look like this if we want to import just the function we’re going to use: from pizza import make_pizza make_pizza(16, 'pepperoni') make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese') With this syntax, you don’t need to use the dot notation when you call a function. Because we’ve explicitly imported the function make_pizza() in the import statement, we can call it by name when we use the function. Using as to Give a Function an Alias If the name of a function you’re importing might conflict with an exist- ing name in your program or if the function name is long, you can use a short, unique alias—an alternate name similar to a nickname for the func- tion. You’ll give the function this special nickname when you import the function. Here we give the function make_pizza() an alias, mp(), by importing make_pizza as mp. The as keyword renames a function using the alias you provide: from pizza import make_pizza as mp mp(16, 'pepperoni') mp(12, 'mushrooms', 'green peppers', 'extra cheese') The import statement shown here renames the function make_pizza() to mp() in this program. Any time we want to call make_pizza() we can simply write mp() instead, and Python will run the code in make_pizza() while avoid- ing any confusion with another make_pizza() function you might have writ- ten in this program file. The general syntax for providing an alias is: from module_name import function_name as fn

Functions 157 Using as to Give a Module an Alias You can also provide an alias for a module name. Giving a module a short alias, like p for pizza, allows you to call the module’s functions more quickly. Calling p.make_pizza() is more concise than calling pizza.make_pizza(): import pizza as p p.make_pizza(16, 'pepperoni') p.make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese') The module pizza is given the alias p in the import statement, but all of the module’s functions retain their original names. Calling the functions by writing p.make_pizza() is not only more concise than writing pizza.make_pizza(), but also redirects your attention from the module name and allows you to focus on the descriptive names of its functions. These function names, which clearly tell you what each function does, are more important to the readability of your code than using the full module name. The general syntax for this approach is: import module_name as mn Importing All Functions in a Module You can tell Python to import every function in a module by using the aster- isk (*) operator: from pizza import * make_pizza(16, 'pepperoni') make_pizza(12, 'mushrooms', 'green peppers', 'extra cheese') The asterisk in the import statement tells Python to copy every func- tion from the module pizza into this program file. Because every function is imported, you can call each function by name without using the dot notation. However, it’s best not to use this approach when you’re working with larger modules that you didn’t write: if the module has a function name that matches an existing name in your project, you can get some unexpected results. Python may see several functions or variables with the same name, and instead of importing all the functions separately, it will overwrite the functions. The best approach is to import the function or functions you want, or import the entire module and use the dot notation. This leads to clear code that’s easy to read and understand. I include this section so you’ll recognize import statements like the following when you see them in other people’s code: from module_name import *

158 Chapter 8 styling functions You need to keep a few details in mind when you’re styling functions. Functions should have descriptive names, and these names should use lowercase letters and underscores. Descriptive names help you and others understand what your code is trying to do. Module names should use these conventions as well. Every function should have a comment that explains concisely what the function does. This comment should appear immediately after the function definition and use the docstring format. In a well-documented function, other programmers can use the function by reading only the description in the docstring. They should be able to trust that the code works as described, and as long as they know the name of the function, the arguments it needs, and the kind of value it returns, they should be able to use it in their programs. If you specify a default value for a parameter, no spaces should be used on either side of the equal sign: def function_name(parameter_0, parameter_1='default value') The same convention should be used for keyword arguments in func- tion calls: function_name(value_0, parameter_1='value') PEP 8 (https://www.python.org/dev/peps/pep-0008/ ) recommends that you limit lines of code to 79 characters so every line is visible in a reasonably sized editor window. If a set of parameters causes a function’s definition to be longer than 79 characters, press enter after the opening parenthesis on the definition line. On the next line, press tab twice to separate the list of arguments from the body of the function, which will only be indented one level. Most editors automatically line up any additional lines of parameters to match the indentation you have established on the first line: def function_name( parameter_0, parameter_1, parameter_2, parameter_3, parameter_4, parameter_5): function body... If your program or module has more than one function, you can sepa- rate each by two blank lines to make it easier to see where one function ends and the next one begins. All import statements should be written at the beginning of a file. The only exception is if you use comments at the beginning of your file to describe the overall program.

Functions 159 try It yourse lf 8-15. Printing Models: Put the functions for the example print_models.py in a separate file called printing_functions.py Write an import statement at the top of print_models.py, and modify the file to use the imported functions 8-16. Imports: Using a program you wrote that has one function in it, store that function in a separate file Import the function into your main program file, and call the function using each of these approaches: import module_name from module_name import function_name from module_name import function_name as fn import module_name as mn from module_name import * 8-17. Styling Functions: Choose any three programs you wrote for this chapter, and make sure they follow the styling guidelines described in this section summary In this chapter you learned how to write functions and to pass arguments so that your functions have access to the information they need to do their work. You learned how to use positional and keyword arguments, and how to accept an arbitrary number of arguments. You saw functions that display output and functions that return values. You learned how to use functions with lists, dictionaries, if statements, and while loops. You also saw how to store your functions in separate files called modules, so your program files will be simpler and easier to understand. Finally, you learned to style your functions so your programs will continue to be well-structured and as easy as possible for you and others to read. One of your goals as a programmer should be to write simple code that does what you want it to, and functions help you do this. They allow you to write blocks of code and leave them alone once you know they work. When you know a function does its job correctly, you can trust that it will continue to work and move on to your next coding task. Functions allow you to write code once and then reuse that code as many times as you want. When you need to run the code in a function, all you need to do is write a one-line call and the function does its job. When you need to modify a function’s behavior, you only have to modify one block of code, and your change takes effect everywhere you’ve made a call to that function. Using functions makes your programs easier to read, and good func- tion names summarize what each part of a program does. Reading a series of function calls gives you a much quicker sense of what a program does than reading a long series of code blocks.

160 Chapter 8 Functions also make your code easier to test and debug. When the bulk of your program’s work is done by a set of functions, each of which has a specific job, it’s much easier to test and maintain the code you’ve written. You can write a separate program that calls each function and tests whether each function works in all the situations it may encounter. When you do this, you can be confident that your functions will work properly each time you call them. In Chapter 9 you’ll learn to write classes. Classes combine functions and data into one neat package that can be used in flexible and efficient ways.

9C l a s s e s Object-oriented programming is one of the most effective approaches to writing soft- ware. In object-oriented programming you write classes that represent real-world things and situations, and you create objects based on these classes. When you write a class, you define the general behavior that a whole category of objects can have. When you create individual objects from the class, each object is automati- cally equipped with the general behavior; you can then give each object whatever unique traits you desire. You’ll be amazed how well real-world situations can be modeled with object-oriented programming. Making an object from a class is called instantiation, and you work with instances of a class. In this chapter you’ll write classes and create instances of those classes. You’ll specify the kind of information that can be stored in instances, and you’ll define actions that can be taken with these instances. You’ll also write classes that extend the functionality of existing classes, so

162 Chapter 9 similar classes can share code efficiently. You’ll store your classes in mod- ules and import classes written by other programmers into your own pro- gram files. Understanding object-oriented programming will help you see the world as a programmer does. It’ll help you really know your code, not just what’s happening line by line, but also the bigger concepts behind it. Knowing the logic behind classes will train you to think logically so you can write programs that effectively address almost any problem you encounter. Classes also make life easier for you and the other programmers you’ll need to work with as you take on increasingly complex challenges. When you and other programmers write code based on the same kind of logic, you’ll be able to understand each other’s work. Your programs will make sense to many collaborators, allowing everyone to accomplish more. Creating and using a Class You can model almost anything using classes. Let’s start by writing a simple class, Dog, that represents a dog—not one dog in particular, but any dog. What do we know about most pet dogs? Well, they all have a name and age. We also know that most dogs sit and roll over. Those two pieces of infor- mation (name and age) and those two behaviors (sit and roll over) will go in our Dog class because they’re common to most dogs. This class will tell Python how to make an object representing a dog. After our class is written, we’ll use it to make individual instances, each of which represents one spe- cific dog. Creating the Dog Class Each instance created from the Dog class will store a name and an age, and we’ll give each dog the ability to sit() and roll_over(): dog.py u class Dog(): v """A simple attempt to model a dog.""" w def __init__(self, name, age): """Initialize name and age attributes.""" x self.name = name self.age = age y def sit(self): """Simulate a dog sitting in response to a command.""" print(self.name.title() + " is now sitting.") def roll_over(self): """Simulate rolling over in response to a command.""" print(self.name.title() + " rolled over!")

Classes 163 There’s a lot to notice here, but don’t worry. You’ll see this structure throughout this chapter and have lots of time to get used to it. At u we define a class called Dog. By convention, capitalized names refer to classes in Python. The parentheses in the class definition are empty because we’re creating this class from scratch. At v we write a docstring describing what this class does. the __init__() Method A function that’s part of a class is a method. Everything you learned about functions applies to methods as well; the only practical difference for now is the way we’ll call methods. The __init__() method at w is a special method Python runs automatically whenever we create a new instance based on the Dog class. This method has two leading underscores and two trailing under- scores, a convention that helps prevent Python’s default method names from conflicting with your method names. We define the __init__() method to have three parameters: self, name, and age. The self parameter is required in the method definition, and it must come first before the other parameters. It must be included in the def- inition because when Python calls this __init__() method later (to create an instance of Dog), the method call will automatically pass the self argument. Every method call associated with a class automatically passes self, which is a reference to the instance itself; it gives the individual instance access to the attributes and methods in the class. When we make an instance of Dog, Python will call the __init__() method from the Dog class. We’ll pass Dog() a name and an age as arguments; self is passed automatically, so we don’t need to pass it. Whenever we want to make an instance from the Dog class, we’ll provide values for only the last two parameters, name and age. The two variables defined at x each have the prefix self. Any variable prefixed with self is available to every method in the class, and we’ll also be able to access these variables through any instance created from the class. self.name = name takes the value stored in the parameter name and stores it in the variable name, which is then attached to the instance being created. The same process happens with self.age = age. Variables that are accessible through instances like this are called attributes. The Dog class has two other methods defined: sit() and roll_over() y. Because these methods don’t need additional information like a name or age, we just define them to have one parameter, self. The instances we create later will have access to these methods. In other words, they’ll be able to sit and roll over. For now, sit() and roll_over() don’t do much. They simply print a message saying the dog is sitting or rolling over. But the concept can be extended to realistic situations: if this class were part of an actual computer game, these methods would contain code to make an animated dog sit and roll over. If this class was written to control a robot, these methods would direct movements that cause a dog robot to sit and roll over.

164 Chapter 9 Creating Classes in Python 2.7 When you create a class in Python 2.7, you need to make one minor change. You include the term object in parentheses when you create a class: class ClassName(object): --snip-- This makes Python 2.7 classes behave more like Python 3 classes, which makes your work easier overall. The Dog class would be defined like this in Python 2.7: class Dog(object): --snip-- Making an Instance from a Class Think of a class as a set of instructions for how to make an instance. The class Dog is a set of instructions that tells Python how to make individual instances representing specific dogs. Let’s make an instance representing a specific dog: class Dog(): --snip-- u my_dog = Dog('willie', 6) v print("My dog's name is " + my_dog.name.title() + ".") w print("My dog is " + str(my_dog.age) + " years old.") The Dog class we’re using here is the one we just wrote in the previous example. At u we tell Python to create a dog whose name is 'willie' and whose age is 6. When Python reads this line, it calls the __init__() method in Dog with the arguments 'willie' and 6. The __init__() method creates an instance representing this particular dog and sets the name and age attributes using the values we provided. The __init__() method has no explicit return statement, but Python automatically returns an instance representing this dog. We store that instance in the variable my_dog. The naming convention is helpful here: we can usually assume that a capitalized name like Dog refers to a class, and a lowercase name like my_dog refers to a single instance cre- ated from a class. accessing attributes To access the attributes of an instance, you use dot notation. At v we access the value of my_dog’s attribute name by writing: my_dog.name Dot notation is used often in Python. This syntax demonstrates how Python finds an attribute’s value. Here Python looks at the instance my_dog

Classes 165 and then finds the attribute name associated with my_dog. This is the same attri- bute referred to as self.name in the class Dog. At w we use the same approach to work with the attribute age. In our first print statement, my_dog.name.title() makes 'willie', the value of my_dog’s name attribute, start with a capital letter. In the second print statement, str(my_dog.age) converts 6, the value of my_dog’s age attribute, to a string. The output is a summary of what we know about my_dog: My dog's name is Willie. My dog is 6 years old. Calling Methods After we create an instance from the class Dog, we can use dot notation to call any method defined in Dog. Let’s make our dog sit and roll over: class Dog(): --snip-- my_dog = Dog('willie', 6) my_dog.sit() my_dog.roll_over() To call a method, give the name of the instance (in this case, my_dog) and the method you want to call, separated by a dot. When Python reads my_dog.sit(), it looks for the method sit() in the class Dog and runs that code. Python interprets the line my_dog.roll_over() in the same way. Now Willie does what we tell him to: Willie is now sitting. Willie rolled over! This syntax is quite useful. When attributes and methods have been given appropriately descriptive names like name, age, sit(), and roll_over(), we can easily infer what a block of code, even one we’ve never seen before, is supposed to do. Creating Multiple Instances You can create as many instances from a class as you need. Let’s create a second dog called your_dog: class Dog(): --snip-- my_dog = Dog('willie', 6) your_dog = Dog('lucy', 3) print("My dog's name is " + my_dog.name.title() + ".") print("My dog is " + str(my_dog.age) + " years old.") my_dog.sit()

166 Chapter 9 print("\nYour dog's name is " + your_dog.name.title() + ".") print("Your dog is " + str(your_dog.age) + " years old.") your_dog.sit() In this example we create a dog named Willie and a dog named Lucy. Each dog is a separate instance with its own set of attributes, capable of the same set of actions: My dog's name is Willie. My dog is 6 years old. Willie is now sitting. Your dog's name is Lucy. Your dog is 3 years old. Lucy is now sitting. Even if we used the same name and age for the second dog, Python would still create a separate instance from the Dog class. You can make as many instances from one class as you need, as long as you give each instance a unique variable name or it occupies a unique spot in a list or dictionary. try It yourse lf 9-1. Restaurant: Make a class called Restaurant The __init__() method for Restaurant should store two attributes: a restaurant_name and a cuisine_type Make a method called describe_restaurant() that prints these two pieces of information, and a method called open_restaurant() that prints a message indi- cating that the restaurant is open Make an instance called restaurant from your class Print the two attri- butes individually, and then call both methods 9-2. Three Restaurants: Start with your class from Exercise 9-1 Create three different instances from the class, and call describe_restaurant() for each instance 9-3. Users: Make a class called User Create two attributes called first_name and last_name, and then create several other attributes that are typically stored in a user profile Make a method called describe_user() that prints a summary of the user’s information Make another method called greet_user() that prints a personalized greeting to the user Create several instances representing different users, and call both methods for each user

Classes 167 working with Classes and Instances You can use classes to represent many real-world situations. Once you write a class, you’ll spend most of your time working with instances created from that class. One of the first tasks you’ll want to do is modify the attributes associated with a particular instance. You can modify the attributes of an instance directly or write methods that update attributes in specific ways. The Car Class Let’s write a new class representing a car. Our class will store information about the kind of car we’re working with, and it will have a method that summarizes this information: car.py class Car(): """A simple attempt to represent a car.""" u def __init__(self, make, model, year): """Initialize attributes to describe a car.""" self.make = make self.model = model self.year = year v def get_descriptive_name(self): """Return a neatly formatted descriptive name.""" long_name = str(self.year) + ' ' + self.make + ' ' + self.model return long_name.title() w my_new_car = Car('audi', 'a4', 2016) print(my_new_car.get_descriptive_name()) At u in the Car class, we define the __init__() method with the self parameter first, just like we did before with our Dog class. We also give it three other parameters: make, model, and year. The __init__() method takes in these parameters and stores them in the attributes that will be associated with instances made from this class. When we make a new Car instance, we’ll need to specify a make, model, and year for our instance. At v we define a method called get_descriptive_name() that puts a car’s year, make, and model into one string neatly describing the car. This will spare us from having to print each attribute’s value individually. To work with the attribute values in this method, we use self.make, self.model, and self.year. At w we make an instance from the Car class and store it in the variable my_new_car. Then we call get_descriptive_name() to show what kind of car we have: 2016 Audi A4 To make the class more interesting, let’s add an attribute that changes over time. We’ll add an attribute that stores the car’s overall mileage.

Python Crash Course (3rd Edition)

@publisher-rmto
إبلاغ