Main
Introduction to Python for Science and Engineering
Introduction to Python for Science and Engineering
David J. Pine
Series in Computational Physics
Steven A. Gottlieb and Rubin H. Landau, Series Editors
Introduction to Python for Science and Engineering
This guide offers a quick and incisive introduction to Python programming for anyone. The author has carefully developed a concise approach to using Python in any discipline of science and engineering, with plenty of examples, practical hints, and insider tips.
Readers will see why Python is such a widely appealing program, and learn the basics of syntax, data structures, input and output, plotting, conditionals and loops, userdefined functions, curve fitting, numerical routines, animation, and visualization. The author teaches by example and assumes no programming background for the reader.
David J. Pine is the Silver Professor and Professor of Physics at New York University, and Chair of the Department of Chemical and Biomolecular Engineering at the NYU Tandon School of Engineering. He is an elected fellow of the American Physical Society and American Association for the Advancement of Science (AAAS), and is a Guggenheim Fellow.
Steven A. Gottlieb and Rubin H. Landau, Series Editors
Introduction to Python for Science and Engineering
This guide offers a quick and incisive introduction to Python programming for anyone. The author has carefully developed a concise approach to using Python in any discipline of science and engineering, with plenty of examples, practical hints, and insider tips.
Readers will see why Python is such a widely appealing program, and learn the basics of syntax, data structures, input and output, plotting, conditionals and loops, userdefined functions, curve fitting, numerical routines, animation, and visualization. The author teaches by example and assumes no programming background for the reader.
David J. Pine is the Silver Professor and Professor of Physics at New York University, and Chair of the Department of Chemical and Biomolecular Engineering at the NYU Tandon School of Engineering. He is an elected fellow of the American Physical Society and American Association for the Advancement of Science (AAAS), and is a Guggenheim Fellow.
Year:
2019
Publisher:
CRC Press
Language:
english
Pages:
389
ISBN 10:
1138583898
ISBN 13:
9781138583894
Series:
Series in Computational Physics
File:
PDF, 5.22 MB
Download (pdf, 5.22 MB)
Preview
 Checking other formats...
 Please login to your account first

Need help? Please read our short guide how to send a book to Kindle.
The file will be sent to your email address. It may take up to 15 minutes before you receive it.
The file will be sent to your Kindle account. It may takes up to 15 minutes before you received it.
Please note you need to add our NEW email km@bookmail.org to approved email addresses. Read more.
Please note you need to add our NEW email km@bookmail.org to approved email addresses. Read more.
You may be interested in
Most frequently terms
python^{679}
array^{388}
plot^{338}
numpy^{292}
arrays^{224}
import^{200}
engineering^{196}
python for science^{183}
introduction to python^{182}
matplotlib^{156}
pandas^{142}
ipython^{141}
programs^{141}
fig^{136}
format^{135}
variable^{132}
plots^{125}
output^{121}
input^{118}
lists^{115}
plotting^{108}
keyword^{100}
variables^{96}
parameters^{94}
animation^{94}
notebook^{91}
jupyter^{90}
scipy^{86}
loop^{84}
columns^{81}
ax1^{80}
nan^{78}
routines^{78}
ax2^{77}
linear^{76}
dataframe^{75}
numerical^{73}
files^{72}
strings^{70}
script^{69}
user^{69}
syntax^{68}
jupyter notebook^{66}
commands^{64}
axes^{63}
def^{62}
lambda^{60}
import matplotlib^{60}
programming^{60}
import numpy^{59}
fitting parameters^{59}
theta^{59}
ing^{57}
spyder^{56}
numpy as np^{56}
equations^{54}
default^{54}
func^{54}
terminal^{54}
directory^{53}
You can write a book review and share your experiences. Other readers will always be interested in your opinion of the books you've read. Whether you've loved the book or not, if you give your honest and detailed thoughts then people will find new books that are right for them.
1

2

Introduction to Python for Science and Engineering Series in Computational Physics Parallel Science and Engineering Applications: The Charm++ Approach Laxmikant V. Kale, Abhinav Bhatele Introduction to Numerical Programming: A Practical Guide for Scientists and Engi neers Using Python and C/C++ Titus A. Beu Computational Problems for Physics: With Guided Solutions Using Python Rubin H. Landau, Manual José Páez Introduction to Python for Science and Engineering David J. Pine For more information about this series, please visit: https://www.crcpress.com/ SeriesinComputationalPhysics/bookseries/CRCSERCOMPHY https://www.crcpress.com/ Introduction to Python for Science and Engineering David J. Pine CRC Press Taylor & Francis Group 6000 Broken Sound Parkway NW, Suite 300 Boca Raton, FL 334872742 © 2019 by Taylor & Francis Group, LLC CRC Press is an imprint of Taylor & Francis Group, an Informa business No claim to original U.S. Government works Printed on acidfree paper International Standard Book Number13: 9781138583894 (Paperback) International Standard Book Number13: 9781138583900 (Hardback) This book contains information obtained from authentic and highly regarded sources. Reasonable efforts have been made to publish reliable data and information, but the author and publisher cannot assume responsibility for the validity of all materials or the consequences of their use. The authors and publishers have attempted to trace the copyright holders of all material reproduced in this publication and apologize to copyright holders if permission to publish in this form has not been obtained. If any copyright material has not been acknowledged please write and let us know so we may rectify in any future reprint. Except as permitted under U.S. Copyright Law, no part of this book may be reprinted, reproduced, trans mitted, or utilized in any form by any electronic, mechanical, or other means, now known or hereafter invented, including photocopying, microfilming, and recording, or in any information storage or retrieval system, without written permission from the publishers. For permission to photocopy or use material electronically from this work, please access www.copyright. com (http://www.copyright.com/) or contact the Copyright Clearance Center, Inc. (CCC), 222 Rosewood Drive, Danvers, MA 01923, 9787508400. CCC is a notforprofit organization that provides licenses and registration for a variety of users. For organizations that have been granted a photocopy license by the CCC, a separate system of payment has been arranged. Trademark Notice: Product or corporate names may be trademarks or registered trademarks, and are used only for identification and explanation without intent to infringe. Visit the Taylor & Francis Web site at http://www.taylorandfrancis.com and the CRC Press Web site at http://www.crcpress.com Library of Congress Cataloging‑in‑Publication Data Names: Pine, David J., author. Title: Introduction to Python for science and engineering / by David J. Pine. Description: Boca Raton, Florida : CRC Press, [2019]  Series: Series in computational physics  Includes bibliographical references and index. Identifiers: LCCN 2018027880 (print)  LCCN 2018051956 (ebook)  ISBN 9780429506413 (eBook General)  ISBN 9780429014253 (eBook Adobe Reader)  ISBN 9780429014246 (eBook ePub)  ISBN 9780429014239 (eBook Mobipocket)  ISBN 9781138583894 (paperback : acidfree paper)  ISBN 9781138583900 (hardback : acidfree paper). Subjects: LCSH: Python (Computer program language)  Computer programming.  EngineeringData processing.  ScienceData processing. Classification: LCC QA76.73.P98 (ebook)  LCC QA76.73.P98 P58 2019 (print)  DDC 005.13/3dc23 LC record available at https://lccn.loc.gov/2018027880 MATLAB® is a trademark of The MathWorks, Inc. and is used with permission. The MathWorks does not warrant the accuracy of the text or exercises in this book. This book’s use or discussion of MATLAB® software or related products does not constitute endorsement or sponsorship by The MathWorks of a particular pedagogical approach or particular use of the MATLAB® software. www.copyright http://www.copyright.com/ http://www.taylorandfrancis.com http://www.crcpress.com https://lccn.loc.gov/2018027880 To Alex Pine who introduced me to Python http://taylorandfrancis.com Contents Preface xv About the Author xix 1 Introduction 1 1.1 Introduction to Python for Science and Engineering . 1 2 Launching Python 3 2.1 Interacting with Python . . . . . . . . . . . . . . . . . 3 2.2 Installing Python on Your Computer . . . . . . . . . . 4 2.3 The Spyder Window . . . . . . . . . . . . . . . . . . . 4 2.4 The IPython Pane . . . . . . . . . . . . . . . . . . . . . 4 2.4.1 Magic commands . . . . . . . . . . . . . . . . . 6 2.4.2 System shell commands . . . . . . . . . . . . . 8 2.4.3 Tab completion . . . . . . . . . . . . . . . . . . 8 2.4.4 Recap of commands . . . . . . . . . . . . . . . . 9 2.5 Interactive Python as a Calculator . . . . . . . . . . . 9 2.5.1 Binary arithmetic operations in Python . . . . . 10 2.5.2 Types of numbers . . . . . . . . . . . . . . . . . 10 2.5.3 Important note on integer division in Python . 12 2.6 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.6.1 Names and the assignment operator . . . . . . 13 2.6.2 Legal and recommended variable names . . . . 14 2.6.3 Reserved words in Python . . . . . . . . . . . . 15 2.7 Script Files and Programs . . . . . . . . . . . . . . . . 16 2.7.1 First scripting example: The Editor pane . . . . 16 2.8 Python Modules . . . . . . . . . . . . . . . . . . . . . . 18 2.8.1 Python modules and functions: A first look . . 20 2.8.2 Some NumPy functions . . . . . . . . . . . . . . 22 2.8.3 Scripting Example 2 . . . . . . . . . . . . . . . 23 2.8.4 Different ways of importing modules . . . . . . 24 2.9 Getting Help: Documentation in IPython . . . . . . . 26 vii viii Contents 2.10 Standalone IPython . . . . . . . . . . . . . . . . . . . 26 2.10.1 Writing Python scripts in a text editor . . . . . 27 2.11 Programming Errors . . . . . . . . . . . . . . . . . . . 28 2.11.1 Pyflakes . . . . . . . . . . . . . . . . . . . . . . 28 2.11.2 Error checking . . . . . . . . . . . . . . . . . . . 29 2.12 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . 29 3 Strings, Lists, Arrays, and Dictionaries 33 3.1 Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 3.2 Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 3.2.1 Slicing lists . . . . . . . . . . . . . . . . . . . . . 37 3.2.2 The range function: Sequences of numbers . . . 38 3.2.3 Tuples . . . . . . . . . . . . . . . . . . . . . . . 39 3.2.4 Multidimensional lists and tuples . . . . . . . . 40 3.3 NumPy Arrays . . . . . . . . . . . . . . . . . . . . . . . 41 3.3.1 Creating arrays (1d) . . . . . . . . . . . . . . . 41 3.3.2 Mathematical operations with arrays . . . . . . 43 3.3.3 Slicing and addressing arrays . . . . . . . . . . 46 3.3.4 Fancy indexing: Boolean masks . . . . . . . . . 47 3.3.5 Multidimensional arrays and matrices . . . . . 49 3.3.6 Differences between lists and arrays . . . . . . 52 3.4 Dictionaries . . . . . . . . . . . . . . . . . . . . . . . . 53 3.5 Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 3.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . 57 4 Input and Output 61 4.1 Keyboard Input . . . . . . . . . . . . . . . . . . . . . . 61 4.2 Screen Output . . . . . . . . . . . . . . . . . . . . . . . 64 4.2.1 Formatting output with str.format() . . . . . 64 4.2.2 Printing arrays . . . . . . . . . . . . . . . . . . . 68 4.3 File Input . . . . . . . . . . . . . . . . . . . . . . . . . 69 4.3.1 Reading data from a text file . . . . . . . . . . . 69 4.3.2 Reading data from an Excel file: CSV files . . . 71 4.4 File Output . . . . . . . . . . . . . . . . . . . . . . . . 73 4.4.1 Writing data to a text file . . . . . . . . . . . . . 73 4.4.2 Writing data to a CSV file . . . . . . . . . . . . 76 4.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . 76 Contents ix 5 Conditionals and Loops 81 5.1 Conditionals . . . . . . . . . . . . . . . . . . . . . . . . 82 5.1.1 if, elif, and else statements . . . . . . . . . . 82 5.1.2 Logical operators . . . . . . . . . . . . . . . . . 86 5.2 Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 5.2.1 for loops . . . . . . . . . . . . . . . . . . . . . . 87 5.2.2 while loops . . . . . . . . . . . . . . . . . . . . . 91 5.2.3 Loops and array operations . . . . . . . . . . . 93 5.3 List Comprehensions . . . . . . . . . . . . . . . . . . . 94 5.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . 96 6 Plotting 99 6.1 An Interactive Session with PyPlot . . . . . . . . . . . 100 6.2 Basic Plotting . . . . . . . . . . . . . . . . . . . . . . . 102 6.2.1 Specifying line and symbol types and colors . . 106 6.2.2 Error bars . . . . . . . . . . . . . . . . . . . . . 108 6.2.3 Setting plotting limits and excluding data . . . 110 6.2.4 Subplots . . . . . . . . . . . . . . . . . . . . . . 113 6.3 Logarithmic Plots . . . . . . . . . . . . . . . . . . . . . 116 6.3.1 Semilog plots . . . . . . . . . . . . . . . . . . . 116 6.3.2 Loglog plots . . . . . . . . . . . . . . . . . . . . 118 6.4 More Advanced Graphical Output . . . . . . . . . . . 118 6.4.1 An alternative syntax for a grid of plots . . . . 122 6.5 Plots with multiple axes . . . . . . . . . . . . . . . . . 125 6.6 Mathematics and Greek symbols . . . . . . . . . . . . 126 6.7 The Structure of matplotlib: OOP and All That . . . . 131 6.7.1 The backend layer . . . . . . . . . . . . . . . . . 132 6.7.2 The artist layer . . . . . . . . . . . . . . . . . . . 135 6.7.3 The PyPlot (scripting) layer . . . . . . . . . . . 137 6.8 Contour and Vector Field Plots . . . . . . . . . . . . . 139 6.8.1 Making a 2D grid of points . . . . . . . . . . . . 139 6.8.2 Contour plots . . . . . . . . . . . . . . . . . . . 140 6.8.3 Streamline plots . . . . . . . . . . . . . . . . . . 144 6.9 ThreeDimensional Plots . . . . . . . . . . . . . . . . . 149 6.10 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . 152 7 Functions 155 7.1 UserDefined Functions . . . . . . . . . . . . . . . . . 156 7.1.1 Looping over arrays in userdefined functions . 158 x Contents 7.1.2 Fast array processing for userdefined functions 160 7.1.3 Functions with more than one input or output 161 7.1.4 Positional and keyword arguments . . . . . . . 162 7.1.5 Variable number of arguments . . . . . . . . . . 163 7.1.6 Passing function names and parameters as argu ments . . . . . . . . . . . . . . . . . . . . . . . . 164 7.2 Passing data (objects) to and from functions . . . . . . 167 7.2.1 Variables and arrays created entirely within a function . . . . . . . . . . . . . . . . . . . . . . 167 7.2.2 Passing lists and arrays to functions: Mutable and immutable objects . . . . . . . . . . . . . . 169 7.3 Anonymous Functions: lambda Expressions . . . . . 171 7.4 NumPy Object Attributes: Methods and Instance Vari ables . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 7.5 Example: Linear Least Squares Fitting . . . . . . . . . 175 7.5.1 Linear regression . . . . . . . . . . . . . . . . . 177 7.5.2 Linear regression with weighting: χ2 . . . . . . 179 7.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . 182 8 Curve Fitting 187 8.1 Using Linear Regression for Fitting Nonlinear Func tions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 8.1.1 Linear regression for fitting an exponential function . . . . . . . . . . . . . . . . . . . . . . 187 8.1.2 Linear regression for fitting a powerlaw func tion . . . . . . . . . . . . . . . . . . . . . . . . . 192 8.2 Nonlinear Fitting . . . . . . . . . . . . . . . . . . . . . 193 8.3 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . 198 9 Numerical Routines: SciPy and NumPy 205 9.1 Special Functions . . . . . . . . . . . . . . . . . . . . . 206 9.2 Random Numbers . . . . . . . . . . . . . . . . . . . . . 209 9.2.1 Uniformly distributed random numbers . . . . 210 9.2.2 Normally distributed random numbers . . . . . 210 9.2.3 Random distribution of integers . . . . . . . . . 211 9.3 Linear Algebra . . . . . . . . . . . . . . . . . . . . . . 212 9.3.1 Basic computations in linear algebra . . . . . . 212 9.3.2 Solving systems of linear equations . . . . . . . 213 9.3.3 Eigenvalue problems . . . . . . . . . . . . . . . 214 Contents xi 9.4 Solving Nonlinear Equations . . . . . . . . . . . . . . 216 9.4.1 Single equations of a single variable . . . . . . 217 9.4.2 Solving systems of nonlinear equations . . . . . 221 9.5 Numerical Integration . . . . . . . . . . . . . . . . . . 221 9.5.1 Single integrals . . . . . . . . . . . . . . . . . . 222 9.5.2 Double integrals . . . . . . . . . . . . . . . . . . 226 9.6 Solving ODEs . . . . . . . . . . . . . . . . . . . . . . . 227 9.7 Discrete (Fast) Fourier Transforms . . . . . . . . . . . 231 9.7.1 Continuous and discrete Fourier transforms . . 231 9.7.2 The SciPy FFT library . . . . . . . . . . . . . . . 232 9.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . 234 10 Data Manipulation and Analysis: Pandas 239 10.1 Reading Data from Files Using Pandas . . . . . . . . . 240 10.1.1 Reading from Excel files saved as csv files . . . 240 10.1.2 Reading from text files . . . . . . . . . . . . . . 247 10.1.3 Reading from an Excel file . . . . . . . . . . . . 250 10.2 Dates and Times in Pandas . . . . . . . . . . . . . . . . 251 10.3 Data Structures: Series and DataFrame . . . . . . . . . 253 10.3.1 Series . . . . . . . . . . . . . . . . . . . . . . . . 253 10.3.2 DataFrame . . . . . . . . . . . . . . . . . . . . . 256 10.4 Getting Data from the Web . . . . . . . . . . . . . . . 261 10.5 Extracting Information from a DataFrame . . . . . . . 263 10.6 Plotting with Pandas . . . . . . . . . . . . . . . . . . . 267 10.7 Grouping and Aggregation . . . . . . . . . . . . . . . 272 10.7.1 The groupby method . . . . . . . . . . . . . . . 273 10.7.2 Iterating over groups . . . . . . . . . . . . . . . 274 10.7.3 Reformatting DataFrames . . . . . . . . . . . . 277 10.7.4 Custom aggregation of DataFrames . . . . . . . 280 10.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . 281 11 Animation 287 11.1 Animating a Sequence of Images . . . . . . . . . . . . 287 11.1.1 Simple image sequence . . . . . . . . . . . . . . 288 11.1.2 Annotating and embellishing videos . . . . . . 292 11.2 Animating Functions . . . . . . . . . . . . . . . . . . . 294 11.2.1 Animating for a fixed number of frames . . . . 295 11.2.2 Animating until a condition is met . . . . . . . 300 11.3 Combining Videos with Animated Functions . . . . . 306 xii Contents 11.3.1 Using a single animation instance . . . . . . . . 307 11.3.2 Combining multiple animation instances . . . 308 11.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . 311 12 Python Classes and GUIs 315 12.1 Defining and Using a Class . . . . . . . . . . . . . . . 316 12.1.1 The __init__() method . . . . . . . . . . . . . 319 12.1.2 Defining methods for a class . . . . . . . . . . . 320 12.1.3 Calling methods from within a class . . . . . . 321 12.1.4 Updating instance variables . . . . . . . . . . . 322 12.2 Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . 323 12.3 Graphical User Interfaces (GUIs) . . . . . . . . . . . . 326 12.3.1 Eventdriven programming . . . . . . . . . . . 327 12.3.2 PyQt . . . . . . . . . . . . . . . . . . . . . . . . 328 12.3.3 A basic PyQt dialog . . . . . . . . . . . . . . . . 328 12.3.4 Summary of PyQt5 classes used . . . . . . . . . 337 12.3.5 GUI summary . . . . . . . . . . . . . . . . . . . 337 A Installing Python 339 A.1 Installing Python . . . . . . . . . . . . . . . . . . . . . 339 A.1.1 Setting preferences . . . . . . . . . . . . . . . . 340 A.1.2 Pyflakes . . . . . . . . . . . . . . . . . . . . . . 340 A.1.3 Updating your Python installation . . . . . . . 341 A.2 Testing Your Installation of Python . . . . . . . . . . . 341 A.3 Installing FFmpeg for Saving Animations . . . . . . . 343 B Jupyter Notebooks 345 B.1 Launching a Jupyter Notebook . . . . . . . . . . . . . 345 B.2 Running Programs in a Jupyter Notebook . . . . . . . 347 B.3 Annotating a Jupyter Notebook . . . . . . . . . . . . . 348 B.3.1 Adding headings and text . . . . . . . . . . . . 349 B.3.2 Comments with mathematical expressions . . . 350 B.4 Terminal commands in a Jupyter notebook . . . . . . 351 B.5 Plotting in a Jupyter Notebook . . . . . . . . . . . . . 351 B.6 Editing and Rerunning a Notebook . . . . . . . . . . . 353 B.7 Quitting a Jupyter Notebook . . . . . . . . . . . . . . . 353 B.8 Working with an Existing Jupyter Notebook . . . . . . 353 C Glossary 355 Contents xiii D Python Resources 359 D.1 Python Programs and Data Files Introduced in This Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359 D.2 Web Resources . . . . . . . . . . . . . . . . . . . . . . 359 D.3 Books . . . . . . . . . . . . . . . . . . . . . . . . . . . . 361 Index 363 http://taylorandfrancis.com Preface The aim of this book is to provide science and engineering students a practical introduction to technical programming in Python. It grew out of notes I developed for various undergraduate physics courses I taught at NYU. While it has evolved considerably since I first put pen to paper, it retains its original purpose: to get students with no previ ous programming experience writing and running Python programs for scientific applications with a minimum of fuss. The approach is pedagogical and “bottom up,” which means start ing with examples and extracting more general principles from that experience. This is in contrast to presenting the general principles first and then examples of how those general principles work. In my experience, the latter approach is satisfying only to the instructor. Much computer documentation takes a topdown approach, which is one of the reasons it’s frequently difficult to read and understand. On the other hand, once examples have been seen, it’s useful to ex tract the general ideas in order to develop the conceptual framework needed for further applications. In writing this text, I assume that the reader: • has never programmed before; • is not familiar with programming environments; • is familiar with how to get around a Mac or PC at a very basic level; and • is competent in basic algebra, and for Chapters 8 and 9, calculus, linear algebra, ordinary differential equations, and Fourier analy sis. The other chapters, including 10–12, require only basic algebra skills. This book introduces, in some depth, four Python packages that are important for scientific applications: NumPy, short for Numerical Python, provides Python with a multi dimensional array object (like a vector or matrix) that is at the cen ter of virtually all fast numerical processing in scientific Python. xv xvi Introduction to Python for Science & Engineering It is both versatile and powerful, enabling fast numerical compu tation that, in some cases, approaches speeds close to those of a compiled language like C, C++, or Fortran. SciPy, short for Scientific Python, provides access through a Python interface to a very broad spectrum of scientific and numerical soft ware written in C, C++, and Fortran. These include routines to numerically differentiate and integrate functions, solve differen tial equations, diagonalize matrices, take discrete Fourier trans forms, perform leastsquares fitting, as well as many other numer ical tasks. matplotlib is a powerful plotting package written for Python and capable of producing publicationquality plots. While there are other Python plotting packages available, matplotlib is the most widely used and is the de facto standard. Pandas is a powerful package for manipulating and analyzing data formatted and labeled in a manner similar to a spreadsheet (think Excel). Pandas is very useful for handling data produced in exper iments, and is particularly adept at manipulating large data sets in different ways. In addition, Chapter 12 provides a brief introduction to Python classes and to PyQt5, which provides Python routines for building graphical user interfaces (GUIs) that work on Macs, PCs, and Linux platforms. Chapters 1–7 provide the basic introduction to scientific Python and should be read in order. Chapters 8–12 do not depend on each other and, with a few mild caveats, can be read in any order. As the book’s title implies, the text is focused on scientific uses of Python. Many of the topics that are of primary importance to com puter scientists, such as objectoriented design, are of secondary im portance here. Our focus is on learning how to harness Python’s abil ity to perform scientific computations quickly and efficiently. The text shows the reader how to interact with Python using IPython, which stands for Interactive Python, through one of three different interfaces, all freely available on the web: Spyder, an inte grated development environment, Jupyter Notebooks, and a simple IPython terminal. Chapter 2 provides an overview of Spyder and an introduction to IPython, which is a powerful interactive environment Preface xvii tailored to scientific use of Python. Appendix B provides an introduc tion to Jupyter notebooks. Python 3 is used exclusively throughout the text with little refer ence to any version of Python 2. It’s been nearly 10 years since Python 3 was introduced and there is little reason to write new code in Python 2; all the major Python packages have been updated to Python 3. Moreover, once Python 3 has been learned, it’s a simple task to learn how Python 2 differs, which may be needed to deal with legacy code. There are many lucid web sites dedicated to this sometimes necessary but otherwise mindnumbing task. The scripts, programs, and data files introduced in this book are available at https://github.com/djpine/pythonsciengpublic. Finally, I would like to thank Étienne Ducrot, Wenhai Zheng, and Stefano Sacanna for providing some of the data and images used in Chapter 11, and Mingxin He and Wenhai Zheng for their critical read ing of early versions of the text. https://github.com/djpine/pythonsciengpublic http://taylorandfrancis.com About the Author David Pine has taught physics and chemical engineering for over 30 years at four different institutions: Cornell University (as a graduate student), Haverford College, UCSB, and, at NYU, where he is a Profes sor of Physics, Mathematics, and Chemical & Biomolecular Engineer ing. He has taught a broad spectrum of courses, including numerical methods. He does research in experimental softmatter physics, which is concerned with materials such as polymers, emulsions, and col loids. These materials constitute most of the material building blocks of biological organisms. xix http://taylorandfrancis.com chapter 1 Introduction 1.1 Introduction to Python for Science and Engineering This book is meant to serve as an introduction to the Python program ming language and its use for scientific computing. It’s ok if you have never programmed a computer before. This book will teach you how to do it from the ground up. The Python programming language is useful for all kinds of sci entific and engineering tasks. You can use it to analyze and plot data. You can also use it to numerically solve science and engineering prob lems that are difficult or even impossible to solve analytically. While we want to marshal Python’s powers to address scientific problems, you should know that Python is a general purpose com puter language that is widely used to address all kinds of comput ing tasks, from web applications to processing financial data on Wall Street and various scripting tasks for computer system management. Over the past decade it has been increasingly used by scientists and engineers for numerical computations, graphics, and as a “wrapper” for numerical software originally written in other languages, like For tran and C. Python is similar to MATLAB®, another computer language that is frequently used in science and engineering applications. Like MATLAB®, Python is an interpreted language, meaning you can run your code without having to go through an extra step of compiling, as required for the C and Fortran programming languages. It is also a dy namically typed language, meaning you don’t have to declare variables and set aside memory before using them.1 Don’t worry if you don’t know exactly what these terms mean. Their primary significance for you is that you can write Python code, test, and use it quickly with a minimum of fuss. One advantage of Python compared to MATLAB® is that it is free. It can be downloaded from the web and is available on all the stan dard computer platforms, including Windows, macOS, and Linux. 1Appendix C contains a glossary of terms you may find helpful. 1 2 Introduction to Python for Science & Engineering This also means that you can use Python without being tethered to the internet, as required for commercial software that is tied to a re mote license server. Another advantage is Python’s clean and simple syntax, including its implementation of objectoriented programming. This should not be discounted; Python’s rich and elegant syntax renders a number of tasks that are difficult or arcane in other languages either simpler or more understandable in Python. An important disadvantage is that Python programs can be slower than compiled languages like C. For largescale simulations and other demanding applications, there can be a considerable speed penalty in using Python. In these cases, C, C++, or Fortran is recommended, al though intelligent use of Python’s array processing tools contained in the NumPy module can greatly speed up Python code. Another dis advantage is that, compared to MATLAB®, Python is less well docu mented. This stems from the fact that it is public open source software and thus is dependent on volunteers from the community of develop ers and users for documentation. The documentation is freely avail able on the web but is scattered among a number of different sites and can be terse. This manual will acquaint you with the most commonly used web sites. Search engines like Google can help you find others. You are not assumed to have had any previous programming ex perience. However, the purpose of this manual isn’t to teach you the principles of computer programming; it’s to provide a very practical guide to getting started with Python for scientific computing. Perhaps once you see some of the powerful tasks that you can accomplish with Python, you will be inspired to study computational science and en gineering, as well as computer programming, in greater depth. chapter 2 Launching Python In this chapter you learn about IPython, an interface that allows you to use Python interactively with tools that have been optimized for mathematical and computational tasks. You learn how to use IPython as a calculator and how to add, subtract, multiply, divide, and perform other common mathematical functions. You also learn the basic elements of the Python programming language, including functions, variables, and scripts, which are rudimentary com puter programs. We introduce Python modules, which extend the capabilities of the core Python language and allow you to perform advanced mathematical tasks. You also learn some new ways to navigate your computer’s file directories. Finally, you learn how to get help with Python commands and functions. 2.1 Interacting with Python There are many different ways to interact with Python. For general purpose use, people typically use the Python command shell, which is also called the Python Interpreter or Console. A shell or console is just a window on your computer that you use to issue written commands. For scientific Python, which is what we are concerned with here, peo ple generally use the IPython shell (or console). It has been specifically designed for scientific and engineering use. There are different ways to launch an IPython shell and write Python code. As a beginner, we recommend using an Integrated De velopment Environment or IDE such as Spyder, a popular IDE that we introduce in the following sections. Spyder uses an IPython shell and provides other features that make it a convenient platform for you to learn about Python. Eventually, you will want to learn about other ways of interacting with Python, such as Jupyter Notebooks, which are described in Appendix B. Alternatively, you can interact with Python by writing code using a simple text editor and then running the code 3 4 Introduction to Python for Science & Engineering from an IPython shell. We describe how to do this in §2.10 towards the end of this chapter. In the end, you should learn to interact with Python in all these ways, as each is valuable, depending on the ap plication. For now, however, we begin our exploration of Python with the Spyder IDE. 2.2 Installing Python on Your Computer If you haven’t already installed Python on your computer, see Ap pendix A, which includes instructions for installing Python on Macs running under macOSX and on PCs running under Windows. Once you have installed Python, launch Spyder as directed in Ap pendix A, and wait for the Spyder window to appear, like the one shown in Fig. 2.1. 2.3 The Spyder Window The default Spyder window has three panes: the IPython pane, the Editor pane, and the Help pane. The IPython pane is the primary way that you interact with Python. You can use it to run Python computer programs, test snippets of Python code, navigate through your com puter file directories, and perform system tasks like creating, mov ing, and deleting files and directories. You will use the Editor Pane to write and edit Python programs (or scripts), which are simply se quences of Python commands (code) stored in a file on your computer. The Help Pane in Spyder gives help on Python commands. The individual panes in the Spyder window are reconfigurable and detachable but we will leave them pretty much as they are. How ever, you may want to adjust the overall size of the window to suit your computer screen. You can find more information about Spyder using the Help menu. 2.4 The IPython Pane The default input prompt of the IPython pane looks like this: In [1]: This prompt signifies that Spyder is running the IPython shell. The IPython shell has been specifically designed for scientific and engi Launching Python 5 Help Pane IPython Pane Editor Pane Figure 2.1 Spyder IDE window. neering use. The standard Python interactive shell uses the prompt >>>. You can pretty much do everything you want to do with either shell, but we will be using the IPython shell as we want to take ad vantage of some of its special features for scientific computing. By typing commands at the prompt, IPython can be used to per form various system tasks, such as running programs and creating and moving files around on your computer. This is a different kind of computer interface than the iconbased interface (or graphical user interface, GUI) that you usually use to communicate with your com puter. While it may seem more cumbersome for some tasks, it can be more powerful for other tasks, particularly those associated with programming. Before getting started, we point out that like most modern com puter languages, Python is case sensitive. That is, Python distinguishes between upper and lowercase letters. Thus, two words spelled the same but having different letters capitalized are treated as different names in Python. Keep that in mind as we introduce different com mands. 6 Introduction to Python for Science & Engineering 2.4.1 Magic commands IPython features a number of commands called “magic” commands that let you perform various useful tasks. There are two types of magic commands, line magic commands that begin with %—these are ex ecuted on a single line—and cell magic commands that begin with %%—these are executed on several lines. Here, we concern ourselves only with line magic commands. The first thing to know about magic commands is that you can toggle (turn on and off) the need to use the % prefix for line magic commands by typing %automagic. By default, the Automagic switch is set to ON in the Spyder IDE so you don’t need the % prefix. To set Automagic to OFF, simply type %automagic at the IPython prompt. Cell magic commands always need the %% prefix. In what follows below, we assume that Automagic is OFF and thus use the % sign for magic commands. Navigation commands IPython recognizes several common navigation commands that are used under the Unix/Linux operating systems. In the IPython shell, these few commands work on Macs, PCs, and Linux machines. At the IPython prompt, type %cd ∼ (i.e., “%cd” – “space” – “tilde”, where tilde is found near the upper left corner of most keyboards). This will set your computer to its home (default) directory. In [1]: %cd ~ /Users/pine Next type %pwd (print working directory) and press Return. The con sole should return the path of the current directory of your computer. It might look like this on a Mac: In [2]: %pwd Out[2]: '/Users/pine' or this on a PC: In [3]: %pwd Out[3]: C:\\Users\\pine Typing %cd .. (“%cd” – “space” – two periods) moves the IPython shell up one directory in the directory tree, as illustrated by the set of com mands below. In [4]: %cd .. /Users Launching Python 7 In [5]: %pwd Out[5]: '/Users' The directory moved up one from /Users/pine to /Users. Now type ls (list) and press Return. The console should list the names of the files and subdirectories in the current directory. In [6]: %ls Shared/ pine/ In this case, there are only two directories (indicated by the slash) and no files (although the names of the files may be different for you). Type %cd ∼ again to return to your home directory and then type pwd to verify where you are in your directory tree. Making a directory Let’s create a directory within your documents directory that you can use to store your Python programs. We will call it programs. First, re turn to your home directory by typing %cd ~. Then type %ls to list the files and directories in your home directory. In [7]: %cd ~ /Users/pine In [8]: %ls Applications/ Library/ Pictures/ Desktop/ Movies/ Public/ Documents/ Music/ Downloads/ News/ To create a directory called programs, type %mkdir programs (make directory). Then type %ls to confirm that you have created programs. In [9]: %mkdir programs In [10]: %ls Applications/ Library/ Pictures/ Desktop/ Movies/ Public/ Documents/ Music/ programs/ Downloads/ News/ You should see that a new directory named programs has been added to the list of directories. Next, type %cd programs to navigate to that new directory. In [11]: %cd programs /Users/pine/programs 8 Introduction to Python for Science & Engineering Sometimes, the IPython shell becomes cluttered. You can clean up the shell by typing %clear, which will give you a fresh shell window. The %run magic command A very important magic command is %run filename where filename is the name of a Python program you have created. We haven’t done this yet but include it here just for reference. We will come back to this later in the chapter. There are a lot of other magic commands, most of which we don’t need, and others that we will introduce as we need them. If you are curious about them, you can get a list of them by typing %lsmagic. 2.4.2 System shell commands You can also run system shell commands from the IPython shell by typing ! followed by a system shell command. For Macs running OSX and for Linux machines, this means that Unix (or equivalently Linux) commands can be issued from the IPython prompt. For PCs, this means that Windows (DOS) commands can be issued from the IPython prompt. For example, typing !ls (list) and pressing Return lists all the files in the current directory on a Mac. Typing !dir on a PC does essentially the same thing (note that system shell commands in Windows are not case sensitive). 2.4.3 Tab completion IPython also incorporates a number of shortcuts that make using the shell more efficient. One of the most useful is tab completion. Let’s assume you have been following along and that your are in the direc tory Documents or My Documents. To switch to the directory programs, you could type cd programs. Instead of doing that, type cd prog and then press the TAB key. This will complete the command, provided there is no ambiguity in how to finish the command. In the present case, that would mean that there is no other subdirectory beginning with prog. Tab completion works with any command you type into the IPython terminal. Try it out! It will make your life more wonderful. A related shortcut involves the ↑ key. If you type a command, say cd and then press the ↑ key, IPython will complete the cd com mand with the last instance of that command. Thus, when you launch Launching Python 9 IPython, you can use this shortcut to take you to the directory you used when you last ran IPython. You can also simply press the ↑ key, which will recall the most recent command. Repeated application of the ↑ key scrolls through the most recent commands in reverse order. The ↓ key can be used to scroll in the other direction. 2.4.4 Recap of commands Let’s recap the most useful commands introduced above: %pwd : (print working directory) Prints the path of the current direc tory. %ls : (list) Lists the names of the files and directories located in the current directory. %mkdir filename : (make directory) Makes a new directory filename. %cd directoryname : (change directory) Changes the current direc tory to directoryname. Note: for this to work, directoryname must be a subdirectory in the current directory. Typing %cd changes to the home directory of your computer. Typing %cd .. moves the console one directory up in the directory tree. %clear : Clears the IPython screen of previous commands. %run filename : Runs (executes) a Python script. Described later in §2.7.1. Tab completion: Provides convenient shortcuts, with or without the arrow keys, for executing commands in the IPython shell. 2.5 Interactive Python as a Calculator You can use the IPython shell to perform simple arithmetic calcula tions. For example, to find the product 3 × 15, you type 3*15 at the In prompt and press Return: In [1]: 3*15 Out[1]: 45 Python returns the correct product, as expected. You can do more complicated calculations: 10 Introduction to Python for Science & Engineering In [2]: 6+21/3 Out[2]: 13.0 Let’s try some more arithmetic: In [3]: (6+21)/3 Out[3]: 9.0 Notice that the effect of the parentheses in In [3]: (6+21)/3 is to cause the addition to be performed first and then the division. With out the parentheses, Python will always perform the multiplication and division operations before performing the addition and subtrac tion operations. The order in which arithmetic operations are per formed is the same as for most calculators: exponentiation first, then multiplication or division, then addition or subtraction, then left to right. 2.5.1 Binary arithmetic operations in Python Table 2.1 below lists the binary arithmetic operations in Python. It has all the standard binary operators for arithmetic, plus a few you may not have seen before. Operation Symbol Example Output addition + 12+7 19 subtraction  127 5 multiplication * 12*7 84 division / 12/7 1.714285 floor division // 12//7 1 remainder % 12%7 5 exponentiation ** 12**7 35831808 Table 2.1 Binary operators. “Floor division,” designated by //, means divide and keep only the integer part without rounding. “Remainder,” designated by the symbol %, gives the remainder after floor division. 2.5.2 Types of numbers There are three different types of numbers in Python: integers, float ing point numbers, and complex numbers. Integers in Python are simply, as their name implies, integers. Launching Python 11 They can be positive or negative and can be arbitrarily long. In Python, a number is automatically treated as an integer if it is writ ten without a decimal. This means that 23, written without a decimal point, is an integer and 23., written with a decimal point, is a floating point number. Here are some examples of integer arithmetic: In [4]: 12*3 Out[4]: 36 In [5]: 4+5*6(21*8) Out[5]: 134 In [6]: 11/5 Out[6]: 2.2 In [7]: 11//5 # floor divide Out[7]: 2 In [8]: 9734828*79372 Out[8]: 772672768016 For the binary operators +, , *, and //, the output is an integer if the inputs are integers. The output of the division operator / is a floating point as of version 3 of Python. If an integer output is desired when two integers are divided, the floor division operator // must be used. Floating point numbers are essentially rational numbers and can have a fractional part; integers, by their very nature, have no frac tional part. In most versions of Python running on PCs or Macs, floating point numbers go between approximately ±2 × 10−308 and ±2× 10308. Here are some examples of floating point arithmetic: In [9]: 12.*3 Out[9]: 36.0 In [10]: 5**0.5 Out[10]: 2.23606797749979 In [11]: 11./5. Out[11]: 2.2 In [12]: 11.//5. Out[12]: 2.0 In [13]: 11.%5. Out[13]: 1.0 12 Introduction to Python for Science & Engineering In [14]: 6.022e23*300. Out[14]: 1.8066e+26 Note that the result of any operation involving only floating point numbers as inputs is another floating point number, even in the cases where the floor division // or remainder % operators are used. The last output also illustrates an alternative way of writing floating point numbers as a mantissa followed by e or E followed by a power of 10: so 1.23e12 is equivalent to 1.23× 10−12. We also used the exponentiation operator ** to find the square root of 5 by using a fractional power of 0.5. Complex numbers are written in Python as a sum of a real and imaginary part. For example, the complex number 3 − 2i is repre sented as 32j in Python where j represents √ −1. Here are some ex amples of complex arithmetic: In [15]: (2+3j)*(4+9j) Out[15]: (35+6j) In [16]: (2+3j)/(4+9j) Out[16]: (0.19587628865979380.3092783505154639j) In [17]: 2.53j**2 Out[17]: (11.5+0j) In [18]: (2.53j)**2 Out[18]: (2.7515j) Notice that you need to enclose the real and imaginary parts of a com plex number in parentheses if you want operators to operate on the entire complex number. If you multiply an integer by a floating point number, the result is a floating point number. If you multiply a floating point number by a complex number, the result is a complex number. Python promotes the result to the most complex of the inputs. 2.5.3 Important note on integer division in Python One peculiarity of all versions of Python prior to version 3 is that dividing two integers by each other yields the “floor division” result—another integer. Therefore 3/2 yields 1 whereas 3./2 or 3/2. or 3./2. all yield 1.5. Starting with version 3 of Python, all of the above expressions, including 3/2 yield 1.5. Fortunately, we are using version 3 of Python so 3/2 yields 1.5. However, you may Launching Python 13 run into other installations of Python that use version 2, so you should be aware of this point. You can force versions of Python prior to version 3 to divide integers like version 3 does by typing from __future__ import division at the beginning of an IPython ses sion. You only need to type it once and it works for the entire session. 2.6 Variables 2.6.1 Names and the assignment operator A variable is a name that is used to store data. It can be used to store different kinds of data, but here we consider a simple case where the data is a single numerical value. Here are a few examples: In [1]: a = 23 In [2]: p, q = 83.4, 2**0.5 The equal sign “=” is the assignment operator. In the first statement, it creates an integer a and assigns it a value of 23. In the second state ment it creates two floating point numbers p and q and assigns them the values of 83.4 and 1.4142135623730951, respectively. To be more precise, when we write a = 5, Python creates an in teger object and assigns it a value of 5. When we write p, q = 83.4, 2**0.5, Python creates two floating point objects and assigns each its own value. Note that Python stores the numerical value, not the ex pression used to generate it. Thus, q is assigned the 17digit number 1.4142135623730951 generated by evaluating the expression 2**0.5, not with √ 2. (Actually the value of q is stored as a binary, base 2, num ber using scientific notation with a mantissa and an exponent.) In the previous paragraph, we said that the assignment operator creates an object. We will have much more to say about Python ob jects later on, with an explicit discussion of what they are in §3.5. But for now, it suffices to say that variable objects, like a, p, and q defined above, contain both data values, such as 23, 83.4, and 1.4142135623730951, as well as information about the data, such as the data type. For these cases, that data stored in the variable a is a single integer while the data stored in p is a floating point number, as is q. The assignment variable works from right to left; that is, it assigns the value of the number on the right to the variable name on the left. 14 Introduction to Python for Science & Engineering Therefore, the statement “5=a” makes no sense in Python. The assign ment operator “=” in Python is not equivalent to the equals sign “=” we are accustomed to in algebra. The assignment operator can be used to increment or change the value of a variable. In [3]: a = a+1 In [4]: a Out[4]: 24 The statement, a = a+1 makes no sense in algebra, but in Python (and most computer languages), it makes perfect sense: it means “add 1 to the current value of a and assign the result to a.” This construction appears so often in computer programming that there is a special set of operators to perform such changes to a variable: +=, =, *=, and /=. Here are some examples of how they work: In [5]: c , d = 4, 7.92 In [6]: c += 2 In [7]: c Out[7]: 6 In [8]: c *= 3 In [9]: c Out[9]: 18 In [10]: d /= 2 In [11]: d Out[11]: 3.96 In [12]: d = 4 In [13]: d Out[13]: 7.96 By the way, %=, **=, and //=, are also valid operators. Verify that you understand how the above operations work. 2.6.2 Legal and recommended variable names Variable names in Python must start with a letter or an underscore “_” and can be followed by as many alphanumeric characters as you Launching Python 15 like, including the underscore character “_”. Spaces are not allowed in variable names. No other character that is not a letter or a number is permitted. Although variable names can start with the underscore character, you should avoid doing so in most cases. Variables beginning with an underscore are generally reserved for special cases, with which we need not concern ourselves here. Recall that Python is case sensitive, so the variable b is distinct from the variable B. We recommend giving your variables descriptive names as in the following calculation: In [14]: distance = 34. In [15]: time_traveled = 0.59 In [16]: velocity = distance/time_traveled In [17]: velocity Out[17]: 57.6271186440678 The variable names distance, time_traveled, and velocity immedi ately remind you of what is being calculated here. This is good prac tice. But so is keeping variable names reasonably short, so don’t go nuts! 2.6.3 Reserved words in Python There are also some names or words that are reserved by Python for special purposes. You must avoid using these names as variables, which are provided in Table 2.2 for your reference. False class finally is return None continue for lambda try True def from nonlocal while and del global not with as elif if or yield assert else import pass break except in raise Table 2.2 Reserved names in Python. 16 Introduction to Python for Science & Engineering 2.7 Script Files and Programs Performing calculations in the IPython shell is handy if the calcula tions are short. But calculations quickly become tedious when they are more than a few lines long. If you discover you made a mistake at some early step, for example, you may have to go back and retype all the steps subsequent to the error. Having code saved in a file means you can just correct the error and rerun the code without having to retype it. Saving code can also be useful if you want to reuse it later, perhaps with different inputs. For these and many other reasons, we save code in computer files. We call the sequence of commands stored in a file a script or a program or sometimes a routine. Programs can become quite sophisticated and complex. Here we are only going to introduce the simplest features of programming by writing a very simple script. Later, we will introduce some of the more advanced features of programming. To write a script you need a text editor. In principle, any text edi tor will do, but it’s more convenient to use an editor that was designed for the task. We are going to use the Editor of the Spyder IDE (see Fig. 2.1). The Spyder Editor, like most good programming editors, pro vides syntax highlighting, which color codes keywords, comments, and other features of the Python syntax according to their function, and thus makes it easier to read the code and easier to spot pro gramming mistakes. The Spyder Editor also provides syntax check ing, much like a spellchecker in a word processing program, that identifies many coding errors. This can greatly speed the coding pro cess. Tab completion also works in the Editors. 2.7.1 First scripting example: The Editor pane Let’s work through an example to see how scripting works. Suppose you are going on a road trip and you would like to estimate how long the drive will take, how much gas you will need, and the cost of the gas. It’s a simple calculation. As inputs, you will need the distance of the trip, your average speed, the cost of gasoline, and the mileage (average miles per gallon) of your car. Writing a script to do these calculations is straightforward. First, launch Spyder. You should see a tab with the word untitled at the top left of the Editor Pane (see Fig. 2.1). If you don’t, go to the File menu and select New File. Use the mouse to place your cursor at the top of Launching Python 17 the Editor pane. Enter the following code and save the code in a file called myTrip.py. Place the file in the directory programs that you cre ated earlier (see §2.4.1). This stores your script (or program) on your computer’s disk. The exact name of the file is not important but the extension .py is essential. It tells the computer, and more importantly Python, that this is a Python program. Code: chapter2/programs/myTrip.py 1 # Calculates time, gallons of gas used, and cost of 2 # gasoline for a trip 3 distance = 400. # miles 4 mpg = 30. # car mileage 5 speed = 60. # average speed 6 costPerGallon = 2.85 # price of gas 7 8 time = distance/speed 9 gallons = distance/mpg 10 cost = gallons*costPerGallon The number (or hash) symbol # is the “comment” character in Python; anything on a line following # is ignored when the code is ex ecuted. Judicious use of comments in your code will make your code much easier to understand days, weeks, or months after the time you wrote it. Use comments generously. For aesthetic reasons, the com ments on different lines have been aligned. This isn’t necessary. The trailing spaces needed to align the comments have no effect on the running of the code. Now you are ready to run the code. Before doing so, you first need to use the IPython console to move to the programs directory where the file containing the code resides. That is, from the IPython console, use the cd command to move to the programs directory. For example, you might type In [1]: %cd ~/Documents/programs/ To run or execute a script, simply type %run filename, which in this case means type %run myTrip.py (if you have IPython’s Automagic switch turned on, as described in §2.4.1, you can omit the percent sign and just type run filename). When you run a script, Python simply executes the sequence of commands in the order they appear. In [2]: %run myTrip.py Once you have run the script, you can see the values of the variables calculated in the script simply by typing the name of the variable. IPython responds with the value of that variable. 18 Introduction to Python for Science & Engineering In [3]: time Out[3]: 6.666666666666667 In [4]: gallons Out[4]: 13.333333333333334 In [5]: cost Out[5]: 38.0 You can change the number of digits IPython displays using the magic command %precision: In [6]: %precision 2 Out[6]: ' %.2f' In [7]: time Out[7]: 6.67 In [8]: gallons Out[8]: 13.33 In [9]: cost Out[9]: 38.00 Typing %precision returns IPython to its default state; %precision %e causes IPython to display numbers in exponential format (scientific notation). Note about printing If you want your script to return the value of a variable (that is, print the value of the variable to your computer screen), use the print func tion. For example, at the end of our script, if we include the code print(time) print(gallons) print(cost) the script will return the values of the variables time, gallons, and cost that the script calculated. We will discuss the print function in much greater detail, as well as other methods for data output, in Chapter 4. 2.8 Python Modules The Python computer language consists of a “core” language plus a vast collection of supplementary software that is contained in mod Launching Python 19 ules (or packages, which are collections of modules—we’ll not fuss about the distinction here). Many of these modules come with the standard Python distribution and provide added functionality for performing computer system tasks. Other modules provide more spe cialized capabilities that not every user may want. You can think of these modules as a kind of library from which you can borrow ac cording to your needs. You gain access to a module using the import command, which we introduce in the next section. We will need four Python modules that are not part of the core Python distribution, but are nevertheless widely used for scientific computing. The four modules are: NumPy is the standard Python package for scientific computing with Python. It provides the allimportant NumPy array data struc ture, which is at the very heart of NumPy. It also provides tools for creating and manipulating arrays, including indexing and sort ing, as well as basic logical operations and elementbyelement arithmetic operations like addition, subtraction, multiplication, division, and exponentiation. It includes the basic mathemati cal functions of trigonometry, exponentials, and logarithms, as well as a vast collection of special functions (Bessel functions, etc.), statistical functions, and random number generators. It also includes a large number of linear algebra routines that over lap with those in SciPy, although the SciPy routines tend to be more complete. You can find more information about NumPy at http://docs.scipy.org/doc/numpy/reference/index.html. SciPy provides a wide spectrum of mathematical functions and nu merical routines for Python. SciPy makes extensive use of NumPy arrays so when you import SciPy, you should always import NumPy too. In addition to providing basic mathematical func tions, SciPy provides Python “wrappers” for numerical software written in other languages, like Fortran, C, or C++. A “wrapper” provides a transparent easytouse Python interface to standard numerical software, such as routines for doing curve fitting and numerically solving differential equations. SciPy greatly extends the power of Python and saves you the trouble of writing software in Python that someone else has already written and optimized in some other language. You can find more information about SciPy at http://docs.scipy.org/doc/scipy/reference/. http://docs.scipy.org/doc/numpy/reference/index.html http://docs.scipy.org/doc/scipy/reference/ 20 Introduction to Python for Science & Engineering matplotlib is the standard Python package for making two and threedimensional plots. matplotlib makes extensive use of NumPy arrays. You will make all of your plots in Python using this package. You can find more information about matplotlib at http://matplotlib.sourceforge.net/. Pandas is a Python package providing a powerful set of data analysis tools. It uses data structures similar to those used in a spreadsheet program like Excel, and allows you to manipulate data in ways similar to what is done using spreadsheets. You can find more in formation about Pandas at http://pandas.pydata.org/. We will use these four modules extensively and therefore will pro vide introductions to their capabilities as we develop Python. The links above provide much more extensive information and you will certainly want to refer to them from time to time. 2.8.1 Python modules and functions: A first look Because the modules listed above, NumPy, SciPy, matplotlib, and Pan das, are not part of core Python, they need to be imported before we can gain access to their functions and data structures. Here, we show how to import the NumPy module and use some of its functions. We defer introducing NumPy arrays, mentioned in the previous section, until §3.3. We gain access to the NumPy package using Python’s import state ment: In [1]: import numpy After running this statement, we have access to all the functions and data structures of NumPy. For example, we can now access NumPy’s sine function as follows: In [2]: numpy.sin(0.5) Out[2]: 0.479425538604203 In this simple example, the sin function has one argument, here 0.5, and the function returns the sine of that argument, which is assumed to be expressed in units of radians. Note that we had to put the prefix numpy dot before the name of the actual function name sin. This tells Python that the sin function is part of the NumPy module that we just imported. There is another Python module called math that also has a sine http://matplotlib.sourceforge.net/ http://pandas.pydata.org/ Launching Python 21 function. We can import the math module just like we imported the NumPy module: In [3]: import math In [4]: math.sin(0.5) Out[4]: 0.479425538604203 These two sine functions are not the same function, even though in this case they give the same answer. Consider, for example, what hap pens if we ask each function to find the sine of a complex number: In [5]: numpy.sin(3+4j) Out[5]: (3.85373803791937727.016813258003932j) In [6]: math.sin(3+4j)  TypeError Traceback (most recent call last) <ipythoninput24b48edfeaf02a> in <module>() > 1 math.sin(3+4j) TypeError: can't convert complex to float The NumPy sine function works just fine and returns a complex re sult. By contrast, the math sine function returns a error message be cause it does not accept a complex argument. In fact, the math sine function accepts only a single real number as an argument while the numpy sine function accepts real and complex NumPy arrays, which we introduce in §3.3, as arguments. For single real arguments, the math sine function executes faster than the numpy function, but the difference in execution speed is not noticeable in most cases. The important lesson here is to appreciate how Python allows you to extend its capabilities by importing additional packages, while at the same time keeping track of where these capabilities come from using the prefix dot syntax. By using different prefixes, each module maintains its own namespace, that is, its own separate dictionary of names, so that functions with the same name in different packages do not clash. If you are using a lot of NumPy functions, writing out numpy dot before each function can be a little verbose. Python allows you to de fine an abbreviation for the prefix when you import a library. Here we show how to do it for NumPy: In [7]: import numpy as np In [8]: np.sin(0.5) Out[8]: 0.47942553860420301 22 Introduction to Python for Science & Engineering The statement import numpy as np imports and assigns the abbrevia tion np for numpy. In principle, you can use any abbreviation you wish. However, it’s common practice to use np for the NumPy module. You are strongly encouraged to abide by this practice so that others read ing your code will recognize what you are doing. 2.8.2 Some NumPy functions NumPy includes an extensive library of mathematical functions. In Table 2.3, we list some of the most useful ones. A complete list is available at https://docs.scipy.org/doc/numpy/reference/. Function Description sqrt(x) square root of x exp(x) exponential of x, i.e., ex log(x) natural log of x, i.e., lnx log10(x) base 10 log of x degrees(x) converts x from radians to degrees radians(x) converts x from degrees to radians sin(x) sine of x (x in radians) cos(x) cosine x (x in radians) tan(x) tangent x (x in radians) arcsin(x) Arc sine (in radians) of x arccos(x) arc cosine (in radians) of x arctan(x) arc tangent (in radians) of x fabs(x) absolute value of x math.factorial(n) n! of an integer round(x) rounds a float to nearest integer floor(x) rounds a float down to nearest integer ceil(x) rounds a float up to nearest integer sign(x) −1 if x < 0, +1 if x > 0, 0 if x = 0 Table 2.3 Some NumPy math functions. The argument of these functions can be a number or any kind of expression whose output produces a number. All of the following ex pressions are legal and produce the expected output: In [9]: np.log(np.sin(0.5)) Out[9]: 0.73516668638531424 In [10]: np.log(np.sin(0.5)+1.0) https://docs.scipy.org/doc/numpy/reference/ Launching Python 23 Out[10]: 0.39165386283471759 In [11]: np.log(5.5/1.2) Out[11]: 1.5224265354444708 Here, we have demonstrated functions with one input and one output. In general, Python functions have multiple inputs and multi ple outputs. We will discuss these and other features of functions later when we take up functions in the context of userdefined functions. 2.8.3 Scripting Example 2 Let’s try another problem. Suppose you want to find the distance be tween two Cartesian coordinates (x1, y1, z1) and (x2, y2, z2). The dis tance is given by the formula ∆r = √ (x2 − x1)2 + (y2 − y1)2 + (z2 − z1)2 Now let’s write a script to do this calculation and save it in a file called twoPointDistance.py. Code: chapter2/programs/twoPointDistance.py 1 # Calculates the distance between two 3d Cartesian 2 # coordinates 3 import numpy as np 4 5 x1, y1, z1 = 23.7, 9.2, 7.8 6 x2, y2, z2 = 3.5, 4.8, 8.1 7 8 dr = np.sqrt((x2x1)**2 + (y2y1)**2 + (z2z1)**2) We have introduced extra spaces into some of the expressions to improve readability. They are not necessary; where and whether you include them is largely a matter of taste. Because we will need the square root function of NumPy, the script imports NumPy before doing anything else. If you leave out the “import numpy as np” line or remove the np dot in front of the sqrt function, you will get the following error message Traceback (most recent call last): ... File ".../twoPointDistance.py", line 8, in <module> dr = sqrt((x2x1)**2 + (y2y1)**2 + (z2z1)**2) NameError: name "sqrt" is not defined 24 Introduction to Python for Science & Engineering Now, with the import numpy as np statement, we can run the script. In [10]: %run twoPointDistance.py In [11]: dr Out[11]: 34.48 The script works as expected. 2.8.4 Different ways of importing modules There are different ways that you can import modules in Python. Importing an entire module Usually we import entire modules using the import statement or the import ... as ... statement that we introduced for the Math and NumPy libraries: import math import numpy as np Importing part of a module You can also import a single function or subset of functions from a module without importing the entire module. For example, suppose you wanted to import just the log function from NumPy. You could write from numpy import log To use the log function in a script, you would write a = log(5) which would assign the value 1.6094379124341003 to the variable a. If you wanted to import the three functions, log, sin, and cos, you would write from numpy import log, sin, cos Imported in this way, you would use them without any prefix as the functions are imported into the general namespace of the program. In general, we do not recommend using from module import functions way of importing functions. When reading code, it makes it harder to determine from which modules functions are imported, and can lead to clashes between similarly named functions from different modules. Nevertheless, we do use this form sometimes and, more importantly, Launching Python 25 you will see the form used in programs you encounter on the web and elsewhere so it is important to understand the syntax. Blanket importing of a module There is yet another way of importing an entire module by writing from numpy import * This imports the entire module, in this case NumPy, into the general namespace and allows you to use all the functions in the module with out a prefix. If you import two different libraries this way in the same script, then it’s impossible to tell which functions come from which library by just looking at the script. You also have the aforementioned problem of clashes between libraries, so you are strongly advised not to import this way in a script or program. There is one possible exception to this advice, however. When working in the IPython shell, you generally just want to try out a func tion or very small snippet of code. You usually are not saving this code in a script; it’s disposable code, never to be seen or used again. In this case, it can be convenient to not have to write out the prefixes. If you like to operate this way, then type pylab at the IPython prompt. This imports NumPy and matplotlib as follows: from numpy import * from matplotlib.pyplot import * In Appendix A, we suggest that you set up Spyder so that it does not automatically launch the IPython shell in “pylab” mode. While you are learning Python, it’s important that you learn which func tions belong to which modules. After you become more expert in Python, you can decide if you want to work in an IPython shell in pylab mode.1 In this text, we do not operate our IPython shell in “pylab” mode. That way, it is always clear to you where the functions we use come from. Whether you choose to operate your IPython shell in pylab mode or not, the NumPy and matplotlib libraries (as well as other libraries) are not available in the scripts and programs you write in the Editor Pane unless you explicitly import these modules, which you would do by writing 1Some programmers consider such advice sacrilege. Personally, I sometimes find pylab mode to be convenient for my workflow. You can decide if it suits you. 26 Introduction to Python for Science & Engineering import numpy as np import matplotlib.pyplot as plt 2.9 Getting Help: Documentation in IPython Help is never far away when you are running the IPython shell. To ob tain information on any valid Python or NumPy function, and many matplotlib functions, simply type help( function ), as illustrated here In [1]: help(range) Help on class range in module builtins: class range(object) class range(object)  range(stop) > range object  range(start, stop[, step]) > range object   Return an object that produces a sequence of integers  from start (inclusive) to stop (exclusive) by step.  range(i, j) produces i, i+1, i+2, ..., j1. start defaults  to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.  These are exactly the valid indices for a list of 4  elements. When step is given, it specifies the increment  (or decrement). Often, the information provided can be quite extensive and you might find it useful to clear the IPython window with the %clear command so you can easily scroll back to find the beginning of the documen tation. You may have also noticed that when you type the name of a function plus the opening parenthesis, IPython displays a small win dow describing the basic operation of that function. One nice feature of the Spyder IDE is that if you place the cursor next to or within a function name and press ’cmdI’ (Mac) or ’ctrlI’ (PC), the web documentation for the function is displayed in the Help Pane. 2.10 Standalone IPython You don’t need the Spyder IDE to run IPython. You can run the IPython shell on its own. To do so, you first need to launch a termi nal application. If you are running the macOS, launch the Terminal Launching Python 27 application, which you can find in the Application/Utilities folder. If you are running Windows, launch the Anaconda Prompt app under the Anaconda (or Anaconda3) menu in the Start menu. Once you launch a terminal application, you should type ipython at the prompt. This will bring up an IPython terminal window with the usual IPython prompt.2 From there, you can execute any valid Python or IPython com mand or function. Note, however, that the NumPy module is not automatically loaded. Therefore, you will need to type import numpy as np and then use the np dot prefix to access any NumPy functions you may wish to use. You can run a Python script by typing %run followed by the script file name. For example, to run the the script myTrip.py, you would type: In [1]: %run myTrip.py Of course, for this to work, the script myTrip.py must be in the work ing director of IPython. If this is not the case, you can use the cd com mand to navigate to the directory in which the script myTrip.py is found. You can close the IPython shell by typing quit(). 2.10.1 Writing Python scripts in a text editor You can write Python scripts using any plain text editor. No special editor or IDE is required. Some editors, however, automatically rec ognize any file whose names ends in the suffix .py as a Python file. For example, the text editor programs Notepad++ (for PCs) or BBEdit (for Macs) recognize Python files. These editors are nice because the color code the Python syntax and provide other useful features. There are many others that work too. One particularly interesting text editor is called Atom. It’s free and available for for Macs, PCs, and Linux machines. It’s highly config urable and can be set up to work as a very effective Python editor. 2You can launch the standard standard Python interactive shell, which is distinct from the IPython shell, simply by typing python and pressing Return. You will get the standard Python prompt >>>. Of course, you won’t get the functionality of the IPython shell with its magic commands, as described in §2.4.1. To close the Python shell, type quit(). 28 Introduction to Python for Science & Engineering 2.11 Programming Errors Now that you have a little experience with Python and computer pro gramming, it’s time for an important reminder: Programming is a detailoriented activity. To be good at computer programming, to avoid frustration when programming, you must pay attention to de tails. A misplaced or forgotten comma or colon can keep your code from working. Note that I did not say it can “keep your code from working well”; it can keep your code from working at all! Worse still, little errors can make your code give erroneous answers, where your code appears to work, but in fact does not do what you intended it to do! So pay attention to the details! 2.11.1 Pyflakes One way to avoid making errors is to use a syntax checker. Fortu nately, a syntax checker is built into the Spyder IDE This is an enor mous asset when writing code and one of the best reasons for using an IDE. A syntaxchecking program called Pyflakes runs in the background when you are editing a Python program using Spyder. If there is an error in your code, Pyflakes flags the error. In Spyder, a red circle appears to the left of the line where Pyflakes thinks the error occurs. Sometimes, the error actually occurs in the previous line, so look around. A yellow triangle appears to the left of the line where Pyflakes thinks that the coding style doesn’t conform to the PEP 8 standard;3 it’s not an error, just a coding style violation, which you can heed or ignore. Passing your mouse pointer over the red or yellow icon brings up a Code Analysis box with a brief message describing the error or style violation. In this text, we have mostly heeded the PEP 8 style guidelines (see https://www.python.org/dev/peps/pep0008). We advise you to do the same. PEP 8 is Python’s style guide and its aim is to enhance code readability. The simplest way to learn the style guidelines is to heed the messages associated with the yellow triangle icons. Doing so will make the yellow icons disappear and will generally render your code more consistent and readable. 3PEP stands for Python Enhancement Proposal. https://www.python.org/dev/peps/pep0008 Launching Python 29 2.11.2 Error checking This raises a second point: sometimes your code will run but give the wrong answer because of a programming error or because of a more subtle error in your algorithm, even though there may be noth ing wrong with your Python syntax. The program runs; it just gives the wrong answer. For this reason, it is important to test your code to make sure it is behaving properly. Test it to make sure it gives the correct answers for cases where you already know the correct answer or where you have some independent means of checking it. Test it in limiting cases, that is, for cases that are at the extremes of the sets of parameters you will employ. Always test your code; this is a cardinal rule of programming. 2.12 Exercises 1. A ball is thrown vertically up in the air from a height h0 above the ground at an initial velocity v0. Its subsequent height h and velocity v are given by the equations h = h0 + v0t − 1 2 gt2 v = v0 − gt where g = 9.8 is the acceleration due to gravity in m/s2. Write a script that finds the height h and velocity v at a time t after the ball is thrown. Start the script by setting h0 = 1.6 (meters) and v0 = 14.2 (m/s) and have your script print out the values of height and velocity. Then use the script to find the height and velocity after 0.5 seconds. Then modify your script to find them after 2.0 seconds. 2. Write a script that defines the variables V0 = 10, a = 2.5, and z = 4 1 3 , and then evaluates the expression V = V0 ( 1− z√ a2 + z2 ) . Then find V for z = 823 and print it out (see Note about printing on page 18). Then find V for z = 13 by changing the value of z in your script. 30 Introduction to Python for Science & Engineering 3. Write a single Python script that calculates the following expres sions: (a) a = 2 + e2.8 √ 13− 2 (b) b = 1− (1 + ln2)−3.5 1 + √ 5 (c) c = sin ( 2− √ 2 2 + √ 2 ) After running your script in the IPython shell, typing a, b, or c at the IPython prompt should yield the value of the expressions in (a), (b), or (c), respectively. 4. A quadratic equation with the general form ax2 + bx+ c = 0 has two solutions given by the quadratic formula x = −b ± √ b2 − 4ac 2a . (a) Given a, b, and c as inputs, write a script that gives the numer ical values of the two solutions. Write the constants a, b, and c as floats, and show that your script gives the correct solutions for a few test cases when the solutions are real numbers, that is, when the discriminant b2−4ac ≥ 0. Use the print function in your script, discussed at the end of §2.7.1, to print out your two solutions. (b) Written this way, however, your script gives an error message when the solutions are complex. For example, see what hap pens when a = 1, b = 2, and c = 3. You can fix this using state ments in your script like a = a+0j after setting a to some float value. Thus, you can make the script work for any set of real inputs for a, b, and c. Again, use the print function to print out your two solutions. 5. Write a program to calculate the perimeter p of an ngon inscribed inside a sphere of diameter 1. Find p for n = 3, 4, 5, 100, 10,000, and 1,000,000. Your answers should be Launching Python 31 n p n p 3 2.59807621135 100 3.14107590781 4 2.82842712475 10,000 3.14159260191 5 2.93892626146 1,000,000 3.14159265358 http://taylorandfrancis.com chapter 3 Strings, Lists, Arrays, and Dictionaries In this chapter you learn about data structures, which Python uses to store and organize numerical, alphabetical, and other types of information. The variables introduced in the previous chapter are a very simple kind of data structure. Here we introduce several more data structures that prove useful in programming, including strings, lists, tuples, and dictionaries, which are all part of core Python. We also introduce NumPy arrays, which are very use ful for storing and manipulating scientific data. We introduce a powerful technique called slicing, which allows you to extract and manipulate sections of data contained in lists, tuples, and NumPy arrays. Finally, we introduce some basic ideas about objects, which are central to the underlying structure and functioning of Python. The most important data structure for scientific computing in Python is the NumPy array. NumPy arrays are used to store lists of numerical data and to represent vectors, matrices, and even tensors. NumPy arrays are designed to handle large data sets efficiently and with a minimum of fuss. The NumPy library has a large set of routines for creating, manipulating, and transforming NumPy arrays. NumPy functions, like sqrt and sin, are designed specifically to work with NumPy arrays. Core Python has an array data structure, but it’s not nearly as versatile, efficient, or useful as the NumPy array. We will not be using Python arrays at all. Therefore, whenever we refer to an “array,” we mean a “NumPy array.” We discuss NumPy arrays in §3.3. Lists are another data structure, similar to NumPy arrays, but un like NumPy arrays, lists are a part of core Python. Lists have a variety of uses. They are useful, for example, in various bookkeeping tasks that arise in computer programming. Like arrays, they are sometimes used to store data. However, lists do not have the specialized proper ties and tools that make arrays so powerful for scientific computing. Therefore, we usually prefer arrays to lists for working with scientific data, but there are some circumstances for which using lists is prefer 33 34 Introduction to Python for Science & Engineering able, even for scientific computing. And for other tasks, lists work just fine. We will use them frequently. We discuss them in §3.2. Strings are lists of keyboard characters as well as other characters not on your keyboard. They are not particularly interesting in scien tific computing, but they are nevertheless necessary and useful. Texts on programming with Python typically devote a good deal of time and space to learning about strings and how to manipulate them. Our uses of them are rather modest, however, so we take a minimalist’s ap proach and only introduce a few of their features. We discuss strings in §3.1. Dictionaries are like lists, but the elements of dictionaries are ac cessed in a different way than for lists. The elements of lists and arrays are numbered consecutively, and to access an element of a list or an array, you simply refer to the number corresponding to its position in the sequence. The elements of dictionaries are accessed by “keys,” which can be program strings or (arbitrary) integers (in no particular order). Dictionaries are an important part of core Python. We intro duce them in §3.4. 3.1 Strings Strings are lists of characters. Any character that you can type from a computer keyboard, plus a variety of other characters, can be ele ments in a string. Strings are created by enclosing a sequence of char acters within a pair of single or double quotes. Examples of strings include "Marylyn", 'omg', "good_bad_#5f>", "{0:0.8g}", and 'We hold these truths ...'. Caution: the defining quotes must both be single or both be double quotes when defining a given string. But you can use single quotes to define one string and double quotes to define the next string; it’s up to you and has no consequence. Strings can be assigned variable names In [1]: a = "My dog's name is" In [2]: b = "Bingo" Note that we used double quotes to define the string a, so that we could use the apostrophe (single quote) in dog's. Strings can be con catenated using the “+” operator: In [3]: c = a + " " + b In [4]: c Out[4]: "My dog's name is Bingo" Strings, Lists, Arrays, and Dictionaries 35 In forming the string c, we concatenated three strings, a, b, and a string literal, in this case a space " ", which is needed to provide a space to separate string a from b. You will use strings for different purposes: labeling data in data files, labeling axes in plots, formatting numerical output, requesting input for your programs, as arguments in functions, etc. Because numbers—digits—are also alpha numeric characters, strings can be made up of numbers: In [5]: d = "927" In [6]: e = 927 The variable d is a string while the variable e is an integer. If you try to add them by writing d+e, you get an error. However, if you type d + str(e) or int(d) + e, you get sensible, but different, results. Try them out! 3.2 Lists Python has two data structures, lists and tuples, that consist of a list of one or more elements. The elements of lists or tuples can be numbers or strings, or both. Lists (we discuss tuples later in §3.2.3) are defined by a pair of square brackets on either end with individual elements separated by commas. Here are two examples of lists: In [1]: a = [0, 1, 1, 2, 3, 5, 8, 13] In [2]: b = [5., "girl", 2+0j, "horse", 21] We can access individual elements of a list using the variable name for the list with an integer in square brackets: In [3]: b[0] Out[3]: 5.0 In [4]: b[1] Out[4]: 'girl' In [5]: b[2] Out[5]: (2+0j) The first element of b is b[0], the second is b[1], the third is b[2], and so on. Some computer languages index lists starting with 0, like Python and C, while others index lists (or things moreorless equiv alent) starting with 1 (like Fortran and MATLAB®). It’s important to 36 Introduction to Python for Science & Engineering keep in mind that Python uses the former convention: lists are zero indexed. The last element of this array is b[4], because b has 5 elements. The last element can also be accessed as b[1], no matter how many elements b has, and the nexttolast element of the list is b[2], etc. Try it out: In [6]: b[4] Out[6]: 21 In [7]: b[1] Out[7]: 21 In [8]: b[2] Out[8]: 'horse' Individual elements of lists can be changed. For example: In [9]: b Out[9]: [5.0, 'girl', (2+0j), 'horse', 21] In [10]: b[0] = b[0]+2 In [11]: b[3] = 3.14159 In [12]: b Out[12]: [7.0, 'girl', (2+0j), 3.14159, 21] Here we see that 2 was added to the previous value of b[0] and the string ’horse’ was replaced by the floating point number 3.14159. We can also manipulate individual elements that are strings: In [13]: b[1] = b[1] + "s & boys" In [14]: b Out[14]: [10.0, 'girls & boys', (2+0j), 3.14159, 21] You can also add lists, but the result might surprise you: In [15]: a Out[15]: [0, 1, 1, 2, 3, 5, 8, 13] In [16]: a+a Out[16]: [0, 1, 1, 2, 3, 5, 8, 13, 0, 1, 1, 2, 3, 5, 8, 13] In [17]: a+b Out[17]: [0, 1, 1, 2, 3, 5, 8, 13, 10.0, 'girls & boys', (2+0j), 3.14159, 21] Strings, Lists, Arrays, and Dictionaries 37 Adding lists concatenates them, just as the “+” operator concatenates strings. 3.2.1 Slicing lists You can access pieces of lists using the slicing feature of Python: In [18]: b Out[18]: [10.0, 'girls & boys', (2+0j), 3.14159, 21] In [19]: b[1:4] Out[19]: ['girls & boys', (2+0j), 3.14159] In [20]: b[3:5] Out[20]: [3.14159, 21] You access a subset of a list by specifying two indices separated by a colon “:”. This is a powerful feature of lists that we will use often. Here are a few other useful slicing shortcuts: In [21]: b[2:] Out[21]: [(2+0j), 3.14159, 21] In [22]: b[:3] Out[22]: [10.0, 'girls & boys', (2+0j)] In [23]: b[:] Out[23]: [10.0, 'girls & boys', (2+0j), 3.14159, 21] Thus, if the left slice index is 0, you can leave it out; similarly, if the right slice index is the length of the list, you can leave it out also. What does the following slice of an array give you? In [24]: b[1:1] You can get the length of a list using Python’s len function: In [25]: len(b) Out[25]: 5 You can also extract every second, third, or nth element of a list. Here we extract every second and third element of a list starting at different points: In [26]: b Out[26]: [10.0, 'girls & boys', (2+0j), 3.14159, 21] In [27]: b[0::2] Out[27]: [10.0, (2+0j), 21] 38 Introduction to Python for Science & Engineering In [28]: b[1::2] Out[28]: ['girls & boys', 3.14159] In [29]: b[0::3] Out[29]: [10.0, 3.14159] In [30]: b[1::3] Out[30]: ['girls & boys', 21] In [31]: b[2::3] Out[31]: [(2+0j)] 3.2.2 The range function: Sequences of numbers Because it turns out to be so useful, Python has a special function, range, that can be used to create a uniformly spaced sequence of in tegers. Its general form is range([start,] stop[, step]), where the arguments are all integers; those in square brackets are optional. In its simplest implementation it has only one argument, the stop argu ment: In [32]: list(range(10)) # makes a list of 10 # integers from 0 to 9 Out[32]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] In [33]: list(range(3, 10)) # makes a list of # integers from 3 to 9 Out[33]: [3, 4, 5, 6, 7, 8, 9] In [34]: list(range(0, 10, 2)) # makes a list of 10 # integers from 0 to 9 with an increment of 2 Out[34]: [0, 2, 4, 6, 8] When two or three arguments are used, the first argument gives the first number of the list while the second argument ends the list, but is not included in the list. If the third argument is not included, it’s taken to be 1. In [35]: a = list(range(4, 12)) In [36]: a Out[36]: [4, 5, 6, 7, 8, 9, 10, 11] You can use negative numbers with the range function, and increment the sequence with a number other than 1 using a third entry: In [37]: a = list(range(5, 5, 2)) Strings, Lists, Arrays, and Dictionaries 39 In [38]: a Out[38]: [5, 3, 1, 1, 3] In [39]: a = list(range(5, 0, 1)) In [40]: a Out[40]: [5, 4, 3, 2, 1] The range function makes an iterable sequence In the examples above, we use the list function in conjunction with the range function because by itself the range function does not make a list. The range function simply generates a sequence of numbers one at a time. The only information stored in the range function is the current value of the sequence, the ending value, and the increment. By contrast, a list stores all the numbers in the list. For example, if we type range(10), Python does not return a list. In [41]: range(10) In [42]: range(0, 10) Instead, the Python range(0, 10) function returns an iterable se quence, which saves a lot of memory when the sequence is very long. If this seems a bit vague or confusing at this point, don’t fret. It will become clearer when we introduce for loops in §5.2. 3.2.3 Tuples Next, a word about tuples: tuples are lists that are immutable. That is, once defined, the individual elements of a tuple cannot be changed. Whereas a list is written as a sequence of numbers enclosed in square brackets, a tuple is written as a sequence of numbers enclosed in round parentheses. Individual elements of a tuple are addressed in the same way as individual elements of lists are addressed, but those individual elements cannot be changed. All of this is illustrated by this simple example: In [43]: c = (1, 1, 2, 3, 5, 8, 13) In [44]: c[4] Out[44]: 5 In [45]: c[4] = 7 Traceback (most recent call last): File "<ipythoninput27cb42185162c>", line 1, 40 Introduction to Python for Science & Engineering in <module> c[4] = 7 TypeError: 'tuple' object does not support item assignment When we tried to change c[4], the system returned an error because we are prohibited from changing an element of a tuple. Tuples offer some degree of safety when we want to define lists of immutable con stants. 3.2.4 Multidimensional lists and tuples We can also make multidimensional lists, or lists of lists. Consider, for example, a list of three elements, where each element in the list is itself a list: In [40]: a = [[3, 9], [8, 5], [11, 1]] Here we have a threeelement list where each element consists of a twoelement list. Such constructs can be useful in making tables and other structures. They also become relevant later on in our discussion of NumPy arrays and matrices, which we introduce in §3.3. We can access the various elements of a list with a straightforward extension of the indexing scheme we have been using. The first ele ment of the list a above is a[0], which is [3, 9]; the second is a[1], which is [8, 5]. The first element of a[1] is accessed as a[1][0], which is 8, as illustrated below: In [46]: a[0] Out[46]: [3, 9] In [47]: a[1] Out[47]: [8, 5] In [48]: a[1][0] Out[48]: 8 In [49]: a[2][1] Out[49]: 1 Multidimensional tuples work exactly like multidimensional lists, ex cept they are immutable. Strings, Lists, Arrays, and Dictionaries 41 3.3 NumPy Arrays The NumPy array is the real workhorse of data structures for scien tific and engineering applications. The NumPy array, formally called ndarray in NumPy documentation, is similar to a list but where all the elements of the list are of the same type. The elements of a NumPy ar ray, or simply an array, are usually numbers, but can also be Booleans, strings, or other objects. When the elements are numbers, they must all be of the same type. For example, they might be all integers or all floating point numbers. 3.3.1 Creating arrays (1d) NumPy has a number of functions for creating arrays. We focus on four (or five or six, depending on how you count!). The first of these, the array function, converts a list to an array: In [1]: a = [0, 0, 1, 4, 7, 16, 31, 64, 127] In [2]: import numpy as np In [3]: b = np.array(a) In [4]: b Out[4]: array([ 0, 0, 1, 4, 7, 16, 31, 64, 127]) In [5]: c = np.array([1, 4., 2, 7]) In [6]: c Out[6]: array([ 1., 4., 2., 7.]) Notice that b is an integer array, as it was created from a list of integers. On the other hand, c is a floating point array even though only one of the elements of the list from which it was made was a floating point number. The array function automatically promotes all of the numbers to the type of the most general entry in the list, which in this case is a floating point number. In the case that elements of a list are made up of numbers and strings, all the elements become strings when an array is formed from a list. The second way arrays can be created is using the NumPy linspace or logspace functions. The linspace function creates an ar ray of N evenly spaced points between a starting point and an ending point. The form of the function is linspace(start, stop, N). If the third argument N is omitted, then N=50. 42 Introduction to Python for Science & Engineering In [7]: np.linspace(0, 10, 5) Out[7]: array([ 0. , 2.5, 5. , 7.5, 10. ]) The linspace function produced 5 evenly spaced points between 0 and 10 inclusive. NumPy also has a closely related function logspace that produces evenly spaced points on a logarithmically spaced scale. The arguments are the same as those for linspace except that start and stop refer to a power of 10. That is, the array starts at 10start and ends at 10stop. In [8]: %precision 1 # display 1 digit after decimal Out[8]: '%.1f' In [9]: np.logspace(1, 3, 5) Out[9]: array([ 10. , 31.6, 100. , 316.2, 1000. ]) The logspace function created an array with 5 points evenly spaced on a logarithmic axis starting at 101 and ending at 103. The logspace function is particularly useful when you want to create a loglog plot. The third way arrays can be created is using the NumPy arange function. The form of the function is arange(start, stop, step). If the third argument is omitted step=1. If the first and third arguments are omitted, then start=0 and step=1. In [10]: np.arange(0, 10, 2) Out[10]: array([0, 2, 4, 6, 8]) In [11]: np.arange(0., 10, 2) Out[11]: array([ 0., 2., 4., 6., 8.]) In [12]: np.arange(0, 10, 1.5) Out[12]: array([ 0. , 1.5, 3. , 4.5, 6. , 7.5, 9. ]) The arange function produces points evenly spaced between 0 and 10 exclusive of the final point. Notice that arange produces an integer array in the first case but a floating point array in the other two cases. In general arange produces an integer array if the arguments are all integers; making any one of the arguments a float causes the array that is created to be a float. A fourth way to create an array is with the zeros and ones func tions. As their names imply, they create arrays where all the elements are either zeros or ones. They each take one mandatory argument, the number of elements in the array, and one optional argument that specifies the data type of the array. Left unspecified, the data type is a float. Here are three examples Strings, Lists, Arrays, and Dictionaries 43 In [13]: np.zeros(6) Out[13]: array([ 0., 0., 0., 0., 0., 0.]) In [14]: np.ones(8) Out[14]: array([ 1., 1., 1., 1., 1., 1., 1., 1.]) In [15]: ones(8, dtype=int) Out[15]: np.array([1, 1, 1, 1, 1, 1, 1, 1]) Recap of ways to create a 1d NumPy array array(a): Creates an array from the list a. linspace(start, stop, num): Returns num evenly spaced numbers over an interval from start to stop inclusive. (num=50 if omitted.) logspace(start, stop, num): Returns num logarithmically spaced numbers over an interval from 10start to 10stop inclusive. (num=50 if omitted.) arange([start,] stop[, step,], dtype=None): Returns data points from start to end, exclusive, evenly spaced by step. (step=1 if omitted. start=0 and step=1 if both are omitted.) zeros(num, dtype=float): Returns an an array of 0s with num ele ments. Optional dtype argument can be used to set the data type; left unspecified, a float array is made. ones(num, dtype=float): Returns an an array of 1s with num ele ments. Optional dtype argument can be used to set the data type; left unspecified, a float array is made. 3.3.2 Mathematical operations with arrays The utility and power of arrays in Python comes from the fact that you can process and transform all the elements of an array in one fell swoop. The best way to see how this works is to look at an example. In [16]: a = np.linspace(1., 5, 7) In [17]: a Out[17]: array([1., 0., 1., 2., 3., 4., 5.]) In [18]: a*6 Out[18]: array([ 6., 0., 6., 12., 18., 24., 30.]) 44 Introduction to Python for Science & Engineering Here we can see that each element of the array has been multiplied by 6. This works not only for multiplication, but for any other mathe matical operation you can imagine: division, exponentiation, etc. In [19]: a/5 Out[18]: array([0.2, 0. , 0.2, 0.4, 0.6, 0.8, 1. ]) In [20]: a**3 Out[20]: array([ 1., 0., 1., 8., 27., 64., 125.]) In [21]: a+4 Out[21]: array([ 3., 4., 5., 6., 7., 8., 9.]) In [22]: a10 Out[22]: array([11., 10., 9., 8., 7., 6., 5.]) In [23]: (a+3)*2 Out[23]: array([ 4., 6., 8., 10., 12., 14., 16.]) In [24]: np.sin(a) Out[24]: array([0.8415, 0. , 0.8415, 0.9093, 0.1411, 0.7568, 0.9589]) Here we have set precision 4 so that only 4 digits are displayed to the right of the decimal point. We will typically do this in this manual without mentioning it in order to have neater formatting. Whether or not you do it is entirely up to you. In [25]: np.exp(a) Out[25]: array([ 2.7183, 1. , 0.3679, 0.1353, 0.0498, 0.0183, 0.0067]) In [26]: 1. + np.exp(a) Out[26]: array([ 3.7183, 2. , 1.3679, 1.1353, 1.0498, 1.0183, 1.0067]) In [27]: b = 5*np.ones(8) In [28]: b Out[28]: array([ 5., 5., 5., 5., 5., 5., 5., 5.]) In [29]: b += 4 In [30]: b Out[30]: array([ 9., 9., 9., 9., 9., 9., 9., 9.]) In each case, you can see that the same mathematical operations are performed individually on each element of each array. Even fairly complex algebraic computations can be carried out this way. Strings, Lists, Arrays, and Dictionaries 45 Let’s say you want to create an x − y data set of y = cos x vs. x over the interval from −3.14 to 3.14. Here is how you might do it. In [31]: x = np.linspace(3.14, 3.14, 21) In [32]: y = np.cos(x) In [33]: x Out[33]: array([3.14 , 2.826, 2.512, 2.198, 1.884, 1.57 , 1.256, 0.942, 0.628, 0.314, 0. , 0.314, 0.628, 0.942, 1.256, 1.57 , 1.884, 2.198, 2.512, 2.826, 3.14 ]) In [34]: y Out[34]: array([ 1.0000e+00, 9.5061e01, 8.0827e01, 5.8688e01, 3.0811e01, 7.9633e04, 3.0962e01, 5.8817e01, 8.0920e01, 9.5111e01, 1.0000e+00, 9.5111e01, 8.0920e01, 5.8817e01, 3.0962e01, 7.9633e04, 3.0811e01, 5.8688e01, 8.0827e01, 9.5061e01, 1.0000e+00]) You can use arrays as inputs for any of the functions introduced in §2.8.1. You might well wonder what happens if Python encounters an il legal operation. Here is one example. In [35]: a Out[35]: array([1., 0., 1., 2., 3., 4., 5.]) In [36]: np.log(a) Out[36]: array([ nan, inf, 0. , 0.6931, 1.0986, 1.3863, 1.6094]) We see that NumPy calculates the logarithm where it can, and returns nan (not a number) for an illegal operation, taking the logarithm of a negative number, and inf, or −∞ for the logarithm of zero. The other values in the array are correctly reported. Depending on the settings of your version of Python, NumPy may also print a warning message to let you know that something untoward has occurred. Arrays can also be added, subtracted, multiplied, and divided by each other on an elementbyelement basis, provided the two arrays have the same size. Consider adding the two arrays a and b defined below: In [37]: a = np.array([34., 12, 5.]) 46 Introduction to Python for Science & Engineering In [38]: b = np.array([68., 5.0, 20.]) In [39]: a+b Out[39]: array([ 102., 7., 25.]) The result is that each element of the two arrays are added. Similar results are obtained for subtraction, multiplication, and division: In [40]: ab Out[40]: array([34., 17., 15.]) In [41]: a*b Out[41]: array([ 2312., 60., 100.]) In [42]: a/b Out[42]: array([ 0.5 , 2.4 , 0.25]) These kinds of operations with arrays are called vectorized operations because the entire array, or “vector,” is processed as a unit. Vector ized operations are much faster than processing each element of an array one by one. Writing code that takes advantage of these kinds of vectorized operations is almost always preferred to other means of accomplishing the same task, both because it is faster and because it is usually syntactically simpler. You will see examples of this later on when we discuss loops in Chapter 5. 3.3.3 Slicing and addressing arrays Arrays can be sliced in the same ways that strings and lists can be sliced—any way you slice it! Ditto for accessing individual array el ements: 1d arrays are addressed the same way as strings and lists. Slicing, combined with the vectorized operations can lead to some pretty compact and powerful code. Suppose, for example, that we have two arrays y, and t for position vs. time of a falling object, say a ball, and we want to use these data to calculate the velocity as a function of time: In [43]: y = np.array([0., 1.3, 5. , 10.9, 18.9, 28.7, 40.]) In [44]: t = np.array([0., 0.49, 1. , 1.5 , 2.08, 2.55, 3.2]) We can get find the average velocity for time interval i by the for mula v1 = yi − yi−1 ti − ti−1 Strings, Lists, Arrays, and Dictionaries 47 We can easily calculate the entire array of velocities using the slicing and vectorized subtraction properties of NumPy arrays by noting that we can create two y arrays displaced by one index. In [45]: y[:1] Out[45]: array([ 0. , 1.3, 5. , 10.9, 18.9, 28.7]) In [46]: y[1:] Out[46]: array([ 1.3, 5. , 10.9, 18.9, 28.7, 40. ]) The elementbyelement difference of these two arrays is In [47]: y[1:]y[:1] Out[47]: array([ 1.3, 3.7, 5.9, 8. , 9.8, 11.3]) The elementbyelement difference of the two arrays y[1:]y[:1] di vided by t[1:]t[:1] gives the entire array of velocities. In [48]: v = (y[1:]y[:1])/(t[1:]t[:1]) In [49]: v Out[49]: array([ 2.6531, 7.2549, 11.8 , 13.7931, 20.8511, 17.3846]) Of course, these are the average velocities over each interval so the times best associated with each interval are the times halfway in be tween the original time array, which we can calculate using a similar trick of slicing: In [50]: tv = (t[1:]+t[:1])/2. In [51]: tv Out[51]: array([ 0.245, 0.745, 1.25 , 1.79 , 2.315, 2.875]) 3.3.4 Fancy indexing: Boolean masks There is another way of accessing various elements of an array that is both powerful and useful. We will illustrate with a simple example. Consider the following array In [52]: b = 1.0/np.arange(0.2, 3, 0.2) In [53]: b Out[53]: array([ 5. , 2.5 , 1.66666667, 1.25 , 1. , 0.83333333, 0.71428571, 0.625 , 0.55555556, 0.5 , 0.45454545,