Você está na página 1de 124

GETTINGSTARTEDWITH

Python

JOSELUISROBERTOASUNCION,
GERALDBRITTON

SecondEdition(May2015)


This work is licensed under a
Creative Commons Attribution-NoDerivatives 4.0 International License
.

Trademarks
IBM,the IBMlogo, and ibm.com are trademarks or registeredtrademarksofInternational BusinessMachines Corp.,
registered in many jurisdictions worldwide. Other product and service names might be trademarks of IBM or other
companies. A current list of IBM trademarks is available on the Web at
Copyright and trademark information at
www.ibm.com/legal/copytrade.shtml .
Java and all Javabased trademarks are trademarks of SunMicrosystems,Inc.in theUnitedStates,other countries,
orboth.
MicrosoftandWindowsaretrademarksofMicrosoftCorporationintheUnitedStates,othercountries,orboth.
LinuxisaregisteredtrademarkofLinusTorvaldsintheUnitedStates,othercountries,orboth.
UNIXisaregisteredtrademarkofTheOpenGroupintheUnitedStatesandothercountries.
Othercompany,product,orservicenamesmaybetrademarksorservicemarksofothers.

TableofContents
Chapter1QuickStart
1.1HelloWorld!
1.2InstallingandsettingupPython
1.3DataScientistWorkbench
1.11Summary
Chapter2:Fundamentals
2.2Documentation
2.2.1Comments
2.2.2Docstrings
2.3BasicSyntax
2.3.1AssignmentStatements
2.3.3OtherArithmeticOperators:
2.3.4ConditionalExecution
2.3.5Compoundarithmeticexpressions
2.3.6CompoundLogicalExpressions
2.3.7Expressionchaining
2.3.8EverythinghasaBooleanValue:
2.3.9SpecialOperations:
2.3.10Repetition
2.4ExercisesforChapter2
Chapter3Functions
3.1TheBigPicture
3.2TheBuiltinFunctions
3.2.1ExamplesofBuiltinFunctions
3.2.1FileOperations
3.2.2ListsandTuples
3.2.2.2Builtinmethodsforusewithlistsandtuples
3.2.2.3Comprehensions
3.2.3FormattingOutput
3.3TheStandardLibrary
3.3.1Themathmodule
3.3.2TheOSModule
3.3.3ThePlatformModule
3.3.4Thesysmodule
3.4UserDefinedFunctions
3.4.1Basics
3.4.2GeneratorsandGeneratorExpressions
3.4.3Closures
3.4.4Decorators
3.4.5CoroutinesandConsumers
3.5LambdaExpressions
3.6Exercises
Chapter4Sequences,MappingsandCollections
4.1Sequences
4.2Morefunwithstrings

4.2.1Multilinestrings
4.2.2OtherStringMethods
4.2.3Moreonlists
4.2.4Updatinganddeletinglistitems
4.2.5Operatorsandmethodsforlistsandtuples
4.3Sets
4.3.1IntroductiontoPythonSets
4.3.2Setoperations
4.3.3SetTesting
4.3.4Setsasrelations
4.3.5SetMethods
4.3.6ImmutableSets
4.4Dictionaries
4.4.1Buildingdictionaries
4.4.2Buildingdictionarieswithlistcomprehensions
4.4.2ModifyingDictionaryEntries
4.4.3DictionariesasKeyedRelations
4.4.4IteratingOveraDictionary
4.4.5DictionaryMethods
4.4.6UsingDictionariestoCategorizeandCount
4.4.7Usingdefaultdict
4.5NamedTuples
4.6DoubleendedQueues
4.7Exercises
Chapter5Modules
5.1TheBigPicture
5.2Introduction
5.3Defintion
5.4ImportingModules
5.5ExecutingModulesasscripts
5.6Thedir()function
5.7Packages
5.7.1Importingmodulesfrompackages
5.7.2Modulesreferencingfromothermodules
5.8Howdoestheinterpretergoaboutlookingforyourfiles?
Chapter6ObjectOrientedProgramming
6.1TheBigPicture
6.2ObjectOrientedProgrammingversusProceduralProgramming
6.3Classes
6.3CreatinganObject
6.4Attributes
6.5Behaviours
6.6Inheritance
6.6.1ExtendingCreatedClasses
6.7Exercises
Chapter7DatabaseConnectivity
7.1TheBigPicture
7.2Prerequisites
7.3Settingup

7.4UsingIBMDB2withPython
7.5ConnectionObjects
7.6CursorObjects
7.7PerformingSQLqueries
7.7.1SELECT
7.7.2INSERT
7.8Exercises
AppendixASolutionstothereviewquestions
Chapter2
Chapter3
Chapter4
Chapter6
Chapter7
Websites
Books

Preface
Keepingyourskills currentintoday's world isbecoming increasinglychallenging. There are too manynew
technologies being developed, and little time to learn them all. The Big DataUniversity Book Series has
been developed to minimize the time and effort required to learn many of these new technologies. The
booksthat are part of thisseries have correspondingfree onlinecourses inBigDataUniversity.com,soyou
canlearnusingjustthebook,justtheonlinecourse,orboth!

ThisbookisintendedforanyonewhoworkswithorintendstodevelopPythonapplicationssuchas
applicationdevelopers,consultants,softwarearchitects,datascientists,instructorsandstudents.Itisa
goodreferenceaswellfordevops,systemadministratorsandproductmanagers.

This book was created by the community a community consisting of university professors, students, and
professionals (including IBM employees). The online version of this book isreleasedto the community at
nocharge.Numerousmembersofthecommunityfromaround the worldhaveparticipatedindevelopingthis
book, which will also be translated to several languages by the community. If you would like to provide
feedback, contribute new material, improve existing material, or help with translating thisbooktoanother
language, please send an email of your planned contribution to admin@bigdatauniversity.com with the
subjectGettingStartedwithPythonbookfeedback.

If you are interested in Python becauseyouwant to become a datascientist, orwork with dataanalytics,
makesuretoreviewbigdatauniversity.com,whichhasalargenumberoffreecoursesonthesesubjects.

Abouttheauthors
JoseLuisRobertoAsuncion
Jose isa code qualityfreak. Heplays barbie with objectsby dressingthem upwithdesignpatterns.Heisa
PHPdeveloperby day. Onedayhe wouldlike tofocus workingmorewithJavaandPythonratherthanwith
PHP.Drophimalineattwitter.com/jeunito

GeraldBritton
Gerald Britton is currently a database developer withTD Bankand anopensourcecontributor to various
Pythonbased projects, includingGrampsand OpenLP. Geraldhasbeenactiveindatabase development
for four decadesand has worked both inNorthAmericaandoverseas helping companiesandcharitieswith
their database needs across a variety of platforms, including Linux, Windows and OS/390. Heis alsoa
strong advocatefor the open source software developmentmodel with a dedicationto findingbetter,faster
andcheaperwaysofhandlingdifficultproblems.

Contributors
Thefollowingpeopleedited,reviewed,providedcontent,andcontributedsignificantlytothisbook.

Contributor Company/ Position/Occupation Contribution


University
PolongLin UniversityofToronto MSc.Psychology Additionof
contentrelated
totheData
Scientist
workbench.
Technicaland
Englishreview
andediting
AntonioCangiano IBMTorontoLab SoftwareDeveloperand Technicalreview
TechnicalEvangelist
RaulF.Chong IBMTorontoLab SeniorProgramManager Reviewand
editing

Chapter1QuickStart
1

Welcome to Python! This book aims to get you started on learning Python as quickly as possible. No
previous programmingexperience isassumed. We willshowyoua basic Pythonprogram andthenwewill
getyoustartedoncreatingyourown!

1.1HelloWorld!
LetscreateourfirstPythonprogram.Listing1.1hasthePythoncode.

"""ThisismyfirstprograminPythonYAY!"""
print"Hello,World!"

Listing1.1TheHelloWorld!program
The output of the program,asyoumayhaveguessedisHello,World!Thefirstlinein thelistingissimplya
comment.
To runtheprogramoninteractivemode,start acommandprompt(onWindows,ifyouhavePython installed
already)orterminal(onLinux/MacOS)andtype:
>>>print"Hello,World!"
Python is very simple. Ithasbeendesigned so thatthecode is easytoreadand isasunderstandable as
everydayEnglish.

1.2InstallingandsettingupPython
The first steptowork withPythonistodownloadandinstall itforyour platform.Ifyou'reusingLinux orMac,
Python is already installed on your system. For example, on Linux, you can verify Python isinstalledby
openingaterminalwindow,typingpythonandpressingenter.Ifcorrectlyinstalled,outputsimilartotheone
shownin Figure1.1
shouldappear.

Figure1.1VerifyingifPythonhasbeeninstalledonLinux

ForWindowsusers,followthesestepstogetPythonupandrunningonyourcomputer:
1. Download the Python interpreter from http://www.python.org/downloads/ and choose the installer
that fits with your operating system. Install the latest release of version 2.7. (As of this writing,
version2.7.9iscurrent).ThisisshowninFigure1.2.

Note
:Forthepurposesofthisintroduction,wearenotusingPython3.0.Asalanguage,Python3.0has
severalattractivefeaturesandenhancements.However,forthewidestcompatibilitywiththemany
commercialandopensourcelibrariesthatareavailable,wewillstickwithPython2.7.


Figure1.2DownloadingPython

2. After selectingthePythonversiontodownload,a .msifileisdownloaded.Launchitdirectlyafterthe


downloadcompletes. Ifprompted, give the installerpermissiontomakechangestoyourcomputer.
Figures1.3through1.6showtheinstallationpanelsyouwillsee.Theyareselfexplanatory.


Figure1.3InstallingPythonforallusers?


Figure1.4SelectDestinationDirectory


Figure1.5CustomizePython
BesuretoenabletheoptionAddpython.exetoPath"


Figure1.6InstallingPython
python
3.Testtheinstallationbyopeningacommandpromptandtyping: .(Youmayneedto
logoutandlogbackintoWindowsagainforthechangetothePathenvironmentvariableto
takeeffect.)WhenyoureachthePythonprompt,type

print" Helloworld!"

andhittheEnterkey.

1.3DataScientistWorkbench(
datascientistworkbench.com
)
AlthoughyoucancertainlygetstartedwithPythononitsown,youmayfindyourselfwanting
extrafeaturestohelpyousaveyourscripts,organizeyourprojects,anddisplayyouroutputall
inthesameenvironment.Fortunately,therestheDataScientistWorkbench(DSWB)at
https://datascientistworkbench.com .PoweredbyiPython,acommandshellforinteractive
computing,DSWBletsyouwrite,runandsavePythoncode,andevendisplaygraphicswithin
eachdocumentornotebook.DSWBishostedonIBMscloud,allowingyoutoaccessyour
Pythonnotebooksfromanycomputer.Theinterfaceiscustomizable,andletsyouorganizeyour
projectsanddatafileswithease.Bestofall,likePython,itsfree!

TofollowalongthePythoncodeinthistextbook,youcanusePythononitsown,butwe
recommendtakingalookintoDSWBifyouplanonworkingwithPythoninthefuture.Theyhave
someexcellenttutorialstohelpgetyoustartedusingDSWB.

1.11Summary
ItisveryeasytogetstartedwithPython.Onmanysystems(includingLinuxandOSX)the
languageispreinstalled.ForWindowsusers,theinstallationisquickandpainless!

Chapter2:Fundamentals
2
Pythonwasdesignedwithseveralspecificgoalsinmind:

Simpleimplementation(GuidovanRossumwrotetheoriginalversionentirelyonhisown)
Veryhighlevellanguage
Crossplatformportability(writeonce,runanywhere)
Automaticmemorymanagement
Everythingisanobject
Smallnumberofpowerfuldatatypes
Readabilityandexpressivepower
Easytolearnandremember
Predictability
Safety(bugsinaPythonprogramdonotcrashtheinterpreter)
ExtensibilitywithClanguagemodules

Thosegoalshavebeenachievedandmaintainedthroughoutitsmorethantwentyyearshistory.Todaythere
aremanycontributorswhocontinuetorefineandextendthelanguage.
In this chapter, we will look at some of the fundamental things needed to become an effective Python
programmer. Let's dive in and andputPython to work. Thatmeansyouneedtoknowalittlesyntax.We'll
startoffwithafewbasics,butbeforeallelse,let'sbesurewedo one thingright:documentation!

2.2Documentation

Virtually all professional programmers would agree that a program without proper documentation is
incomplete, regardless of the language. Somelanguagesare quiteverbose(e.g. COBOL, whichclaimsto
be "selfdocumenting" to a degree but still can be used to develop inscrutable programs.) Others are
extremely terse (perhaps APL is the best example). Nomatterwhatlanguageisusedtowriteit,aprogram
without documentation will very likely defy understanding and maintenance. Python is no exception
fortunatelyit provides amplefacilitiestoembed documentationwithin each program. Aswegoalong, we'll
showyouhowtodothatand"practicewhatwepreach"aswell.

2.2.1Comments
The most basictype ofdocumentationisaninlinecomment.InPython,acommentbeginswitha#symbol
(variouslycalled anumbersignor a hashmarkor symbol,dependingon where you live) and finisheswith
theendoftheline.Thisisanexampleofacomment:

#Thisisacomment

A comment can start anywhere on a line, and take place even after other Python commands. Many
comment lines in a row can be used to introduce the method or purpose of a larger block of code that
follows. Getin the habit of using both sortsof comments a lot!You'llthank yourself later,when yougo
back to your programandcan'trememberwhy you did whatyoudidorthewayyoudidit.Ifsomeoneelse
"inherits"yourprogram,thatpersonwillbeespeciallythankful.

2.2.2Docstrings
Adocstring(shortfordocumentationstring)isusedtodocumentthepurpose,inputargumentsandreturn
argumentsofafunction,classormethod.Itbeginsandendswiththreedoublequotationmarks.Lines
betweenthebeginningandenddonotneedthequotationmarks.Thisisanexampleofadocstring:

"""
Thisisanexampleofadocstring
"""

We'llstarttousetheseinearnestwhenwebegintoworkonuserdefinedfunctionsinChapter3.

2.3BasicSyntax
InthissectionwewilllookatthebuildingblocksofaPythonprogramtheelementsyouwillneedtobegin
towriterealprograms.We'llalsobeneedingafewtypesofdata.Fornow,we'llstickwithjustthree:
Integers

o Anintegerisjust,well,aninteger!42,forexample.

Floatingpointnumbers

o Afloatingpointnumberusuallyhasadecimalpoint,like3.14159

Strings

o Astringisasequenceofcharactersenclosedinquotationseithersingle,double,
triplesingleortripledouble.e.g.Hello,world,'''Icanusetripleopeningandclosing
quotations.''',"""Pythonisfun!""".IfyouarecomingfromalanguagelikeCyoumaybe
usedtousingdoublequotationsforstringsandsinglequotationsforcharacters.Thatis
actuallyagoodconventionandaonethatwewilltrytostickwith.

2.3.1AssignmentStatements
Most programminglanguageshavesomesortofanassignmentstatement.Thatisa command specific to
the language thatsaysthat some variablename can be usedtorepresent some constant or expression
(which may involve other variablenames).Forexample, inmathematics,we can assigntheproduct of two
ormorenumbersorvariablestoavariablename:

(1)

y
Ifweassignthevalue2tothevariable:

(2)

andthencomputeequation(1)withthis, weshould expectthe variable xtoreceivethevalueof4.Let's do


this in Python! Start the Python interpreter in an interactive mode following the instructions for your
operatingsystem.IfyouarerunningLinux,youmightstartitlikethis:

$python
Python2.7.9(default,Dec102014,12:24:55)
Type"help","copyright","credits"or"license"formoreinformation.
>>>

The ">>>" is the interpreter prompt and this iswhere you can begin enteringPython statements.Wecan
enter equations (2) and (1) directly, except that the multiplication symbol in Python (as in many other
languages)istheasterisk(*):

>>>y=2#setytotheinteger2
>>>x=2*y#compute2timesthevariabley
>>>
The equals sign (=) is recognized by Python as the assignment operator. Thatis,when the equals sign
appearsbetween two operands, the meaning is to assignthevalue ofthesecondoperandtothe firstone.
So, inthefirststatement, the value2isassignedtothevariable yinthesecondstatement the valueofthe
expression 2 * y x
is assigned to the variable . (This isprobablyagoodtime to point out that,inPython,
x
and y
in this exampledo not receive the values 2 and4,respectively,butratherreferences orpointersto
storage locationswhere 2 and4 are stored.Thisis a subtle but important distinction between Pythonand
someoftheotherlanguageswithwhichyoumaybefamiliar.)
Before we go further, let's get one thing out of the way: identifiers. An identifier is a name you give to
something, like avariable.Sointheabove example,"x"isanidentifier.InPython,youcanmakeidentifiers
fromanysequence of letters, numbersand underscores("_")exceptthatthefirstcharacter must
bealetter
or underscore. Try to make your identifiers say something aboutwhat theyareidentifying.Forexample,
"day"isbetterthan"i"ifyou'retalkingaboutadayoftheweekormonth.
Noticethat, aseach statement is entered,Pythonrespondswitha newprompt,whichmeansthatitisready
for input again. Notice also that we used spaces to separate the variable names, numbers, the
multiplication symbol and the "equals" sign. Spacing like this is not required in Python but is heartily
encouraged. Thereis evenaspecialdocument,(calledPython EnhancementProposalnumber8,or simply
PEP8) that goes into greatdetailaboutwhatgoodPythonstyleisandisnot.Inthisbook,wewill attemptto

follow the guidelines of PEP8 and other styleguides.We want you to developgoodhabits from the very
start!

Always surround binary operators with a single space on either


side.

2.3.2CheckingResults
Sofar,sogood.Atthispointwehavetocheckwhetherourmathworkedandifxreallygotthevalue4.To
x
verifythis,simplytypethevariablenameandhitenter:
>>>x
4
>>>
x
Pythondisplaysthecurrentvalueofthevariableontheterminal.Noticethat,ininteractivemode,itisnot
necessarytousetheprintcommandforthis,thoughthatworksjustaswell:
>>>printx
4
>>>

2.3.3OtherArithmeticOperators:
There are other ways to perform various arithmetic operations in Python. For starters, here is a table
showingthePythonoperatorsthatcorrespondtobasicarithmeticoperations:

Mathematical
PythonEquivalent Example Result Operation
Operator

x+y 2+1 3 Addition

xy 21 1 Subtraction

x*y 2*1 2 Multiplication

2/1 2 Integerdivision
x/y
3.0/2 1.5 Realdivision
x//y
3//2 1 Integerdivision

modulo x%y 5%2 1 Remainderofdivision

x**y 2**3 8 Exponentiation

The different types of division in this table demands an explanation. Python recognizes two types of
division:integerandreal.Withintegerdivision,boththedividendand the divisoraretreatedasintegersand
the resultis also an integer.That means that,whenthequotientisnotaninteger, itisrounded
downtothe
closest integer.With real division, the dividend and divisoraretreated asreal numbersandthequotientis
alsoa realnumberwithoutrounding.The//(doubleslash)operatorexplicitlyspecifies thatyouwantinteger

division.We would encourage youtousethedoubleslashoperatorwhen youwantintegerdivisionandnot


relyon Python'sability tochoosethetype of divisionbased on thetypesof thedividend anddivisor.This
practice adheres to another Python principle, "Explicit is better than implicit" one of nineteen such
principlesfoundinPEP20,entitled"TheZenofPython".

Explicit is better than


implicit!

Forexample:
>>>2/3
0
>>>2.0/3
0.66666666666666663
>>>

2.3.4ConditionalExecution

Let's say thatyouwantedtodivideonenumberbyanother,butyouhad noideainadvancewhatthedivisor


wouldbe. Chancesare, at sometime thedivisor would bezero! Inmathematics,theoperation ofdividing
by zero is undefined, so you would want to avoid doing that and maybe tellthe user abouttheproblem.
x
That's easy to do in Pythonusing the if statement. Let'sassume that you aregiventwo variables,and
y
andyouneedtodivide x y
byandavoiddividingbyzero.Onesolutionwouldbe:

>>>x=2
>>>y=3
>>>ify!=0:
...printx/y#onlyattemptdivisionifthedivisorisnonzero
...else:
...print"Ican'tdividebyzero!"
...
0
>>>

This codesnippetdemonstrates the use of the ifstatement. You begin with the word"if",and followitwith
some condition ("y != 0"in this example), and further follow that with a colon. The operator "!=" is the
Python equivalentof theoperator from mathematics. The use of the colon in thiscontextisaconsistent
patternin Pythonandaonethatwillbeencounteredmanytimes.Inthiscontext,itimpliesthat,"Onlydothe
next sectionof codeif the condition aboveistrue."Inthis case, thenextsectionofcodeistheline"printx /
y". Notice that this line is indented four spaces from the if statement that precedes it. Indentation is
required here and indicates that all the indented linesarepart ofa suiteof Pythoncode thatis dependent
upontheifstatement. The use of fourspacesforindentation isoneof the style guidelinesinPEP8,which
weare following. Notice alsothat theindentation givesavisualcluethattheprintstatementissubordinate
totheifstatement.

Use 4 spaces per indentation


level.

TheelsestatementtellsPythonwhattodointhecasewhereyis,infact,zero.(Noticethattheelse
statementisfollowedbyacolonandthatthenextlineisindentedfourspaces.)Let'strythesameexample
withysettozero:

>>>x=2
>>>y=0
>>>ify!=0:
...printx/y#onlyattemptdivisionifthedivisorisnonzero
...else:
...print"Ican'tdividebyzero!"
...
Ican'tdividebyzero!
>>>
Pythondidexactlywhatitwastoldittodo.Itavoidedthedivisionbyzero
andinformedusofitaswell.

Therearemanysituationswhereasimple"eitheror"suchastheaboveexampleisnotuptothejob.
Supposeyouwantedtoprintadifferentphrasedependingonthedayoftheweek.Let'sassumeyouare
givenavariable,day_number,thatisanintegerfrom1to7where1meansMonday,2meansTuesday,...
and7meansSunday.Todothis,wewillusetheelifstatement:

>>>day_number=4#Let'stryThursday!
>>>ifday_number==1:
...print"Monday'schildisfairofface"
...elifday_number==2:
...print"Tuesday'schildisfullofgrace"
...elifday_number==3:
...print"Wednesday'schildisfullofwoe"
...elifday_number==4:
...print"Thursday'schildhasfartogo"
...elifday_number==5:
...print"Friday'schildislovingandgiving"
...elifday_number==6:
...print"Saturday'schildworkshardforaliving"
...elifday_number==7:
...print"ButthechildbornontheSabbathDay"
...print"Isfairandwiseandgoodandgay"
...else:
...print"Thereareonlysevendaysinaweek!"
...
Thursday'schildhasfartogo
>>>

Theelifstatementgivesyouaconvenientwaytolineupvariousconditionssothattheyappearvisuallyasa
unit.Somelanguagesprovideasimilarfunctionthrougha"switch"or"case"statement"elif"isusedin
Pythontodoasimilarthing.

2.3.4OtherConditionalOperators

Pythonincludesafullsuiteofconditionaloperators.ThefollowingtableshowsPythonoperatorsandthe
correspondingmathematicaloperations:

Mathematics
PythonEquivalent Example Result Operation
Operator

x==y 1==2 False Equals

x<y 1<2 True Strictlylessthan

x<=y 1<=2 True Lessthanorequalto

x>y 1>2 False Strictlygreaterthan

x>=y 1>=2 False Greaterthanorequalto

x!=y 1!=2 True


Notequalto
x<>y 3<>4 True

Note that there are two operators that can be used to test the "not equal to" condition. This is a
convenience providedby Python for programmers familiar with other languages (includingSQL).You can
choosewhicheveroneyouprefer,but beconsistent!

2.3.5Compoundarithmeticexpressions

Sofar,we'veonlylookedatverysimpleexpressions.Thingsarenotalwayssosimple!Whatifyouwere
workingonquadraticequations?Forexample,thegeneralequationforaparabolawithaverticalaxisis:

(3)

Pythonallowsyoutobuildacompoundexpressionfromsimplerones,sothetranslationofthisequationinto
Pythonisnotdifficult:

y=a*x**2+b*x+c#Computetheyaxiscoordinateofaquadraticequation

(GoaheadandtrythisinaninteractivePythonsessionusingyourownvaluesfora,b,candx.)

BylookingatthePythonstatementmoreclosely,youmaywonderhowit"knows"thatyouwantittodothe
exponentiationfirst,thenthemultiplicationandfollowthatwithaddition.Afteralltheresultswouldbequite
different(andwrong!)ifthecomputationproceededstrictlyfromlefttorightorfromrighttoleft(Provethisto
yourselfwithvaluesyouchoosefora,b,candx!)Pythonsolvesthisbyobeyingasystemof
precedence formathematicaloperations.Forthearithmeticoperatorswehaveseensofar,operationsare
doneaccordingtothistable,withthetoprowhavingthehighestprecedenceandthebottomrowhavingthe
lowest.

Operator Description
(expression) parentheses
** exponentiation
multiplication,
*
,
/
,
//
,
%division,
modulus
addition,
+
,

subtraction
positive,
+x
,
x
negative

Noticethatthistableintroducesoperatorsthatwehavenotseenbefore:positive(+x)andnegative(x).
Thesearecalled unaryoperatorssincetheyonlyaffectonevariable.Notealsothatwhitespaceisneither
requirednorrecommendedbetweenaunaryoperatoranditstargetso,forexample:

+a*b

iscorrectbut:

+a*b

isnotrecommended(andhardertoreadintheopinionoftheauthors!)

WhatifyouactuallyneedtooverridePython'sbuiltinprecedenceofoperations?Youcandothatbyusing
parentheses.Expressionsinsideparenthesesarealwayscalculatedfirst,fromtheinmostparenthesized
expressiontotheoutermost.Wecouldforcethe(incorrect!)lefttorightevaluationofequation(3)using
parentheses,likethis:

#Useparenthesestoforcestrictlefttorightevaluation
y=(((a*x)**2+b)*x)+c

This is saying: Multiply a by x, then square the resultthen addb andmultiplythenewresult by x finally,
addc.Asanexercise,howwouldyouuseparenthesestoforcerighttoleftevaluationofequation(3)?

2.3.6CompoundLogicalExpressions

We've seen the way to build compound arithmetical expressions. Now what if we need to test for some
combination ofconditions?Forexample, let'ssay thatyouwanttoplaytenniswithafriend,but you will only
do that ifthetemperatureis greater than80 degrees (Fahrenheit)andthereismorethan 70% sunshine.If
wehavetwoPythonvariables,tempandsunshine,wecoulddoitlikethis:

iftemp>80andsunshine>70:
...

Here wehavetwo conditions("temp > 80" and"sunshine > 70") joined by the keyword "and". The suiteof
statements (represented by the ellipsis, "...") following the "if" statement willnotbe executedunless both
conditionsaretrue.Ifyouarealittlemoreflexibleandwillaccepteithercondition,youcouldwrite:

iftemp>80orsunshine>70:
...

We can also expressthesameidea negatively: "I'llplaytennis as longas the temperatureis notlessthan


80andthereisnotlessthan70%sunshine."

ifnot(temp<80)andnot(sunshine<70):
...

Here,we combine theuse ofparenthesesthe"and"keywordandintroduce the "not"keywordaswell.Note


thatthisexpressionviolates
tworulesfromPEP20, "Simple isbetter than complex" and"Beautifulisbetter
thanugly".

Simple is better than


complex.

Beautifulisbetterthanugly.

Following these two rules, we can see thatthe firstcompoundexpression isthe better one. Now thatwe
have three new operators, weneedto putthem inour precedence table so that weknowwhat to expect.
Thenewprecedencetablelookslikethis:

Operator Description
(expression) parentheses
** exponentiation
multiplication,
*
,
/
,
//
,
% division,
modulus
addition,
+
,

subtraction
positive,
+x
,
x
negative
<
,
<=
,
==
,
!=
,
<>
,
>
,
>= comparisons
not BooleanNOT
and BooleanAND
or BooleanOR
if...else Conditionalexpression

Note:Wewillcontinuethediscussionofconditionalexpressionfurtherinthischapter.

2.3.7Expressionchaining

Python offersshorter expressionsforsomecomparisons.Forexample,supposeyouwant toexecutesome


instructions if the variablenamed "fred" islessthan 0 andis also equaltoanothervariable, "nancy". You
couldwriteitthisway:

iffred<0andfred==nancy:

butPythonhasashorthandexpressionthatwilldothesamething:

if0<fred==nancy:

If thatlooks a little odd to you,youare not alone!In fact,Pythonallows unlimited chainingofcomparisons


sothatlongexpressionssuchas:

ifa<b==c<=d>=e:

arevalid!Theadvantagesarethreefold:

1. You onlyhavetowriteeachvariableonce(provided thatyoucanchainthemtogetheras aboveand


stillmakelogicalsense)
2. Pythononlyhastoevaluateeachvariableonce,ifatall.
3. If the expression evaluates false at any point, moving from lefttoright, the remainder of the
expressionisnotevaluated.

shortcircuiting
The last advantage is the result of Python's strategy. Basically, Python will onlyevaluate
what it needs to in order to proceed, savingextra work andavoiding possibleerrors. For example, ifthe
variables"buffalo"and"bill"arenotdefined,thefollowingstatementwillworkjustfine:

>>>if1>2<buffalo<bill:
...print"shouldn'tgethere"
...
>>>

Since the first comparison"1 > 2" evaluatesto False,thevariables"buffalo" and"bill"areneverevaluated,


which isagoodthingsincetheyareundefined! Trythisonyourownandjustforfun,changethe>to< and
observethenewresults.Iftheyaredifferent,canyouexplainwhy?

2.3.8EverythinghasaBooleanValue:

In Python, everything every variable, number, function, collection, sequence, ... (some of which you
haven't evenseenasyet),hasa boolean value. Thatmeansthat you can put anything inaconditionalto
see if it is True or False. As mentioned before, everythingin Python isalsoa pointer. Thisincludesthe
integer"1"whichisapointertoastoragelocationthatholdstheinteger..Whenyouwrite:

ifvar :

you are essentially asking Python to look at whatever "var" pointsto (an operation called dereferencing)
anddetermine the Boolean value of that. If "var"happenstopoint toa number,PythonconsidersitFalseif
the number is equal to zero and true otherwise."var"couldrefer toeitheroftheBoolean constantsTrueor
False(whicharealsokeywordsthatyoucanuse),inwhichcasethevalueisreturneddirectly.

Often, "var" will refer to some other type of Python object, or None. We capitalize "None"herebecause
None is aspecial Pythonconstantthat isuniquefor the lifetime of the programinwhichitisreferredto.If
var pointsto None,itisconsideredFalse inaBooleansense.Thoughwehaven'tdiscussed themyet,itisa
good time to note that empty collections and sequences are considered False and a nonempty other
collectionorsequenceisconsideredTrue.

2.3.9SpecialOperations:

There are a few special operations that should be mentioned at this point. First up, we will discuss the
augmented assignment statements. An augmented assignment is a shorthand way ofmodifying avalue
referred to by some variable. For example, a common programming operation is to increment (or
decrement)acounterbyone.

Typicallythisisdonelikethis:

x=x+1

butIcanuseanaugmentedassignmentstatementtoshortenthisto:

x+=1

The obvious advantagetousinganaugmentedassignmentstatementisthatthereisalotlesstotype.This


is not sucha big deal for this example. However, ifthevariable namewas"monty_pythons_flying_circus",
chancesarethatyouwouldwanttotypethataslittleaspossible.Thereisamoresubtle,behindthescenes
benefit. With the standard assignment statement, "x" is actually evaluated twice using the augmented
assignment means itis evaluatedonlyonce.Onthewhole,it islessworkforyou,lessworkforPythonand
lessworkforthecomputeryouruniton.Useit!

Another specialoperation allowsustoshortcutsomekindsoftests.Consideranifstatementthat isusedto


effectavariableassignment:

ifa:#setcbasedonwhetheraisTrueorFalse
c=a
else:
c=b

Thisisacommonpatternfoundinmanyprograms.InPython,thiscanbeshortenedto:

c=aandb

Python interpretsthisonelinestatementsothattheresult (theassignmentofthevalueofeither"a"or"b"to


"c") is the same as thefullifelsestatementabove. Thatis,if"a"isTrue(accordingtothediscussion above
under "Everything has a Boolean value", "c" is now identified with thesame value as "a", otherwise"c"is
identifiedwiththesamevalueas"b".

Note: In Python, we use the word "binding" to describe the operation of identifying avariable with some
value. Thus, in the example above, "c" is bound to whatever "a" or "b" are bound to,respectively. The
binding operation is accomplished by using pointers to particular storage locations that is, memory
addresses.

Similartotheaboveexample:

c=aandb

means that"ifa evaluatesto False,bind ctowhatever aisboundto(becauseof shortcircuiting),otherwise


bindctowhateverbisboundto."Hereisanexampleofthisshorthandinaction:

>>>0and2<3
0
>>>(0and2)<3
True

In the first statement, following the rules of precedence,"2< 3" is evaluatedfirst the result isTrue.That
means thatthenext expression to be evaluatedis "0 andTrue".Followingtherulesjustgiven,0evaluates
to False, so 0 is returned. In the second statement,we force the Boolean operation to be evaluatedfirst
using parentheses. "0and2"evaluateto2followingtherulesjust given."0<3"evaluatesto True,whichis
what Pythonreturns! Asanexercise,changethe"and"to"or" intheexamplesaboveandconvinceyourself
thatPythonreallybehavesasdescribedinthissection.

The last special operation that we will look at in this section is the conditional expression.A conditional
expressionisonethatusesif...elsetoreturnasinglevalue.Forexample:

a=1ifbelse2#Setatoeither1ortwodependingonb

Thisisthesameasthelonger:

ifb:#Setatoeither1ortwodependingonb
a=1
else:
a=2

Conditional expressions are ausefulshorthandthatcan beusedanywhere aslongasyou arecarefulabout


the rules of precedence. Try variations of these two expressions in an interactive Python session and
convince yourself that the interpreter is behaving correctly in each case. (Rememberthat the conditional
expressionfitsimmediatelybelowthe"or"operatorintheoperatorprecedencetable.)

>>>1+2ifFalseelse4
4
>>>1+(2ifFalseelse4)
5

2.3.10Repetition

Therearenottoomanyinterestingprograms that dousefulthingsandstill runinastraightline from startto


finish. Mostof theprograms involve somekindof arepetition.Thiscanvary from doing math onagiven
value to waiting for . There are two Python statements that can be helpful for these common sorts of
operations.Theseare:
for

and
while
.

Hereisanexampleofasimpleforloopinaction:

>>>foriin1,2,3:
...printi
...
1
2
3
>>>

All this loop does istoprintthe numbers1, 2and 3 insuccession.Nevertheless,it demonstratesthe key
elementsofaforloop.Noticethatthegeneralsyntaxis:

for<identifier>in<things>:
<suite>

The keyword "for" is a variable name that is to be used in theloop.Next comes the keyword"in" which
gives you a hint that something elseshouldfollow.Finallywehavethethingsthat theidentifierwillbeused
toreference. This can bea simplelistsuch asinthe example oran identifier thatreferstosomethingthat
can be iteratedover.Lastly comes theallimportant colon.Afterthefor statement comes the bodyofthe
loop the suiteof instructions that areexecuted aspartof theforloop.Inthisexample,thereisonlyone
instruction:

printi

whichisindented4spacesfromtheforstatementthatprecedesitfollowingtheguidelinesofPEP8.

Forloopscanbenestedandfrequentlymustbeinordertoperformusefulwork.Forexample:

>>>fordayin"Mon","Tue","Wed":
...forletterinday:
...printletter
...
M
o
n
T
u
e
W
e
d
>>>

The outer loop iteratesover the shortenednamesofthefirstthreedaysoftheweek.Theinnerloopiterates


over the lettersineach ofthosenames. (You will learn moreabout stringsand how to takethemapart in
thechapteronSequencesandCollections).Noticetheindentationlevelsoftheouterandinnerloops.

Nowlet'stakealookatasimplewhileloop:

>>>n=5
>>>f=1
>>>whilen>0:
...f=f*n
...n=1
...
>>>f
120
>>>

What is this loop doing? It is computing n! (n factorial) which isthe productof all theintegersup to and
includingagiveninteger.Thegeneralsyntaxis:

while<condition>:
<suite>

The loopwill onlybeginif the condition istrue andwillonlycontinueas longastheconditionremainstrue.


Awhileloopmayalsobenestedifdesired.

Therearetwosituationsthat arisewithinloops that skiptotheendoftheloopor exititbeforeitisfinished.


The first is accomplished with a continue statement and the second through a break statement. For
example, suppose you have a for loop that takes in some integers, but you only want to process these
numbersiftheyareeven:

>>>foriin1,2,3,4,5:
...ifi%2:#Ifimod2isnotzero,gogetthenextnumber
...continue
...printi
...
2
4
>>>

WhatifyouonlywanttoprintsomelettersofthestringWednesday?

>>>forletterin"Wednesday":
...ifletter=="s":
...break
...printletter
...
W
e
d
n
e
>>>

Notice how the break statement causes the loop to stop before it processes all of the letters in
"Wednesday". As another example, suppose you wantto take in some number andprint out thenumbers
betweenitand100:

>>>number=105
>>>whileTrue:
...printnumber
...ifnumber>=100:#Ifwe'vereached100,stopnow
...break
...number=1
...
105
104
103
102
101
100
>>>

Noticethat the loop startswith whileTrue: Thismeansthatthere mustbesomeotherwayofstoppingthe


loop,oritwillrunforever.

2.4ExercisesforChapter2

1. Eachof the following Python statements has oneor more errors. Correcttheerrorsand test your
correctionsinaninteractivePythonsession:

a.
y=2x3#Multiply2by3andassigntheresulttothevariabley

b.
if4=2/2:#Checkif4isequalto2/2
print"4=2/2!"

c.
forxin123:#printthefirstthreepositiveintegersonthree
lines
printx

d.
x=4ifb#assign4toxifbisTrue,otherwiseleaveitalone

e.
whileTrue:
x=1
ifx:continue

2. Fibonaccinumbersaredefinedwiththisfunction:


withseedvalues:


Write a Python program fragmentthat computestheFibonacci number foragiven number n,and
thenprintstheresult.

3. Itispossibletoapproximatethesineofanyrandomvaluex(inradians)usingthisTaylorseries:



Write a Python program fragmentthat performsthiscalculationtosixterms (ofwhichthefirstthree
aregiven)andcompareyourresultstothepublishedsinetables.

4. Write a Pythonprogramfragmentthat,whengivenamonth oftheyearasanintegerbetween1and
12, printsoutthe month name, the number of daysinthemonth (assumeFebruaryalwayshas 28
days)andalsothenameofthebirthstoneassignedtothemonth.

Chapter3Functions
3
3.1TheBigPicture

For mostprogramming languages today,functionsare wheretheactionhappens. Foronething,functions


providetheinterface betweentheprogram andtherealworld. Withoutfunctions,everyprogrammerwould
have to write lowlevel code to read from afile, printdataonaprinter,managethegraphicsonamonitor or
get what a user types ata keyboard. Functions also giveustheabilitytosolve a problem once and then
use that solution everywhere. Imagine that you always had to write the code necessary to calculate a
square root or sort names or add up a bunch of numbers every time you wanted to dothat. Youwould
probably quickly get tired of such repetitive work and the chance ofgetting it wrongwouldincrease each
timeyouhadtowritethesame(oronlyslightlydifferent)codeagain.

Inthis chapter we will beginbyexploringsomeofthefunctionsinthestandardlibrary.Thislibraryprovides


a deep store ofhighlyoptimizedfunctionsforanarrayoftypicaltasks.WewillalsolookatoneofPython's
most pervasivedatatypeslistssincemanyfunctions(andtheirclosecousins,methods) aredesignedto
work with them. We will alsolearnhowtowriteourownfunctionsandhowtouserecursionandclosuresto
makeourlivessimpler.

3.2TheBuiltinFunctions

Whenever you runPython, you have animmediateaccess toaset ofveryusefulfunctionssousefulthat


they arebuiltinandyoucanusethemwithoutfurtherado.Totrythemout,youneedtocallthem.Callinga
functioninPythonisverysimple:

>>>function(arguments)

3.2.1ExamplesofBuiltinFunctions

Let'stryoutafewbuiltinfunctionstoseewhattheydo:

>>>abs(1)#Absolutevalue
1
>>>bin(3)#Converttobinary
'0b11'
>>>chr(97)#Converttocharacter(inverseoford())
'a'

>>>hex(26)#Converttohexadecimal
'0x1a'
>>>int('26')#Convertastringtoaninteger
26
>>>len("HelloWorld")#Returnthelengthoftheargument
11
>>>max(1,2)#Maximumofarguments
2
>>>min('a','b','c')#Minimumofarguments,whichdon'thavetobenumbers!
'a'
>>>oct(35)#Converttooctal
'043'
>>>ord('a')#Converttoaninteger(inverseorchr())
97
>>>str(44)#Converttoastring
'44'
>>>bool(1)#ReturnTrueorFalseaccordingtoBooleanevaluation
True

Currently, there are nearly 150 builtin functions in Python. Refer to the official documentation for a
complete,uptodatelist ofbuiltinfunctions.Thereisonebuiltinfunctionthatisarguablythemostusefulof
all:help(x).TrythesestatementsinaninteractivePythonsession:

help(help)

help(int)

help(max)

help(bool)

As you can see,it producesone ormore screens ofdocumentationabouttheitemyouarerequestinghelp


everything
for. The argument to help() can be any Pythonobject.Since,inPython isan object, you can
requesthelpaboutanythingatall,evenoperators.Forexample,try:

help('+')

orjust:

help#Startinteractivehelp

3.2.1FileOperations

One importantgroup ofbuiltinfunctionswarrantsspecialdiscussionis thegroupusedtoaccessfiles.Let's


startoffbyusingthebuiltinfunctionopen()tocreateafileandgetitreadyforwriting:

>>>myfile=open("my.txt",'w')
That'sallittakes!Nowthefile"my.txt"isopenforwriting.Let'sfillitupwithsomedata:

>>>i=0
>>>whilei<5:
...myfile.writelines("Linenumber"+str(i))
...i+=1
...
>>>myfile.close()

What is going on here? Well, when the open() function was called, it returned a reference to a file
object.Likeallobjectsin Python (even basic objects like integers and strings), ithas"methods"associated
with it that you use to manipulate the object. Under the covers, methods are actually functions that are
designedto work with a particulartype of object. Inthisexample,weusedtwomethodsthat arepartofthe
fileobject (thereareseveralothers).Inthe whileloop,weusedthewritemethodtowritefive linestothefile
wejustopened.(We used the str()builtinfunction to convertthe loop countertoastring.)Whentheloop
finished(thatis,whentheloopcounterbecameequalto5),weusedtheclose()methodtoclosethefile.

Diditwork?Well,let'sreaditandsee:

>>>myfile=open('my.txt','r')
>>>whileTrue:
...line=myfile.readline()
...ifline=='':
...break
...printline
...
Linenumber0
Linenumber1
Linenumber2
Linenumber3
Linenumber4
>>>myfile.close()
>>>

This time,whenwe openedthefile, wespecified thatit was to beopenedforreading.(Thisisactuallythe


default actionso we could have omittedthe argument'r'.) Next, weenteredawhileloopwiththecondition
set to True. That means thatwe need to have something else to stoptheloop orit will beinfinite.Within
the loop, we use the readline() method of the fileobject to read the nextline andassign ittothevariable
"line." Next, we check to see ifthat lineis just anempty string,''. The readline() definition statesthatan
emptystringis returnedwhenEOF(endoffile) isreached. IfwehaveindeedreachedEOF, webreakoutof
thewhileloop.Otherwise,weprintthedatawereceivedfromthereadline()method.

Thereisanother,somewhatmoreconvenientwaytoreadthelinesfromourfile.Wecandoitlikethis:

>>>myfile=open('my.txt','r')
>>>forlineinmyfile:
...printline
...
Linenumber0
Linenumber1
Linenumber2
Linenumber3
Linenumber4
>>>myfile.close()
>>>

This approachuses the factthatthefileobjectincludesan"iterator"thatautomaticallyreturnsallthelinesin


the file and stops at the end offile, without our having to explicitly look for EOF.Many objects in Python
haveiterators.WesawoneinChapter2:strings.Whenwehaveaforlooplikethis:

>>>forletterin"word":
...printletter
...
w
o
r
d
>>>

What wearereallydoingis using the builtin iteratorfor strings,which returnsthestring onecharacterata


time. There is another, very important type of data in Python that uses iterators and for which several
builtinfunctionsaredesigned:lists.

3.2.2ListsandTuples

Lists (and their stuffy, readonly cousins, tuples) are pervasive in Python. Youwouldbe hardpressed to
find any serious Python programthat does notuselistsin somefashion. Definingasimple list ortuple is
easytodo:

>>>mylist=["this","is","my","list"]
>>>mytuple=("this","is","a","tuple")

The brackets (for lists)or parentheses(for tuples) are requiredhereand tell Pythonto builda list ortuple
andreturnareferencetoit.Themaindifference between a list anda tuple isthat atupleis immutable
that is, it may not bechangedonceit iscreated.WhatcanI dowitha list? Well,forstarters,I can loop
overtheitemsinalistlikethis:

>>>foriteminmylist:
...printitem
...

this
is
my
list
>>>

Single items in the list can also be referred tobynumber. The first itemis 0, the second 1 andsoon.To
specify whichitem wewant,we puttheitemnumberinbrackets (thecharacters[and]). Wecanalsocount
fromthe end, using negative numbers,so 1 is the lastitem,2 isthepenultimate itemandsoon.Hereis
onewaytoprintoutthecontentsofmylistbackwards:

>>>i=1
>>>whilei>=4:
...printmylist[i]
...i=1
...
list
a
is
this
>>>

slicing
Itisalsopossibletotakepiecesoutofthelist,usinganotationcalled .Forexample:

>>>printmylist[1:3]
['is','a']
>>>

k
mylist[i:j]is a slice that selects all items with index i <= k < j.
such that Thus, "list" is not included in
mylist[1:3].

3.2.2.2Builtinmethodsforusewithlistsandtuples

Manybuiltin functions aredesignedto operate on lists,tuplesandothertypesthatsupportiteration.These


include:

>>>all([0,1,2])#ReturnsTrueifalllistitemsevaluatetoTrue
False
>>>any([0,1,2])#ReturnsTrueifanylistitemevaluatestoTrue
True
>>>len([0,1,2])#Returnsthenumberofitemsinthelist
3
>>>min([0,1,2])#Returnsthesmallestiteminthelist
0
>>>max([0,1,2])#Returnsthelargestiteminthelist
2

>>>sum([0,1,2])#Addsupalltheitemsinthelist
3
>>>range(5)#Returnsalistofintegersfrom0to4
[0,1,2,3,4]
>>>map(str,range(5))#Returnsalistofintegersconvertedtostrings
['0','1','2','3','4']
>>>filter(bool,range(5))#Returnsalistofonlythoseitemsthatevaluate
toTrue
[1,2,3,4]
>>>

3.2.2.3Comprehensions

Python offers a concise way to build lists and other objects using comprehensions . Basically, Python is
able to understand aspecial kind ofa forloop withinalist ortupledefinition(andothers,includingsetsand
dictionaries) andbuild a list ortupleaccordingtotheresultsreturnedbytheloop.For example,ifIwanteda
listcomprisedofthesquaresofthefirst100integers,Icouldusealistcomprehensiontodoit:

>>>[i**2foriinrange(100)]
[0,1,4,9,16,25,36,49,64,81,100,121,144,169,196,225,...,9801]
>>>

Note:
Wetruncatedthedisplaytomakeitfitcomfortablyinthisdocument.

The list comprehension says, "Foreachinteger from 0to99,insert anitem intothe listequaltothesquare
ofthat integer." To see just how powerful thissyntax is, consider the way to dothesamethingwith other
tools.Perhapsitwouldlooksomethinglikethis:

>>>squares=[]
>>>foriinrange(100):
...squares.append(i**2)
...
>>>

This willaccomplishthesame thingbutittakesthreelinesto doit andtheforloopcontainsseveralvariable


look ups. It isalso about 60% slower. Here area few morecomplicated examplesshowing thepower of
comprehensions:

>>>[(i,j)foriinrange(5)forjinrange(2)]
[(0,0),(0,1),(1,0),(1,1),(2,0),(2,1),(3,0),(3,1),(4,0),(4,
1)]
>>>
Itispossibletonestcomprehensions.Hereweusedthisfacilitytoconstructalistconsistingoftuples.

>>>[(i,j)foriinrange(5)forjinrange(2)ifi+j<3]
[(0,0),(0,1),(1,0),(1,1),(2,0)]
>>>

We can add conditions on the comprehension to limit what is included. There is no limit on what the
conditionscanentail,providedthattheyaresyntacticallyvalid.

>>>tuple([i,j]foriinrange(5)forjinrange(2)if(i+j)%3)
([0,1],[1,0],[1,1],[2,0],[3,1],[4,0],[4,1])

Here weuseacomprehensiontobuild a tuple containingitemsthatare lists, provided thatthe sum of the


items in each list is not a multiple of 3. Notice that we must use the builtin function tuple() to do this.
OtherwisePythonwouldbuildagenerator,whichwewillcoverlaterinthischapter.

3.2.3FormattingOutput

Sooner or later, you will want to exert some control over the appearance of the output of yourprogram.
Perhaps youwill needtowrite atabularreportandensurethatthecolumnslineupproperly.Perhapsyour
outputwillbetheinputtoanotherprogramthatrequiresaparticular format.Perhapsyousimplywanttoadd
sometextaroundtheresultsofyourcalculations.Youcandoafairbitwiththehumbleprintstatement:

>>>print"Thesquareof",2,"is",2**2
Thesquareof2is4

What ifyouwanttoprintatableofsquaresand ensurethatnumbers andtheir squaresareallrightaligned?


Justusingtheprint statement alone,youwouldbe forced to addor removespacestoforcethealignment,
since the numbersor theirsquaresmighthavemultipledigits.Weneedabetter,more consistentapproach,
andthatiswheretheformat()functionandthestringfunctionofthesamenamecometotherescue.

First let us see if we can use the format() function to solve the problem of alignment mentioned int the
precedingparagraph.Wecandothis:

>>>foriinrange(2,12,2):#range()willmakealiststarting at2,endingat
11andincrementingby2
...print"Thesquareof",format(i,">3d"),"is",format(i**2,">3d")
...
Thesquareof2is4
Thesquareof4is16
Thesquareof6is36
Thesquareof8is64
Thesquareof10is100
>>>

Noticehowthenumbers in the outputare rightaligned?This is whatthe format() function did for us.The
first argument given is the value we want to format (the "what"). The second argument is the format
specification (the"how").Thespecification iswritten in a specialminilanguagethat isderivedfromsimilar
output formattingfacilities foundinC andother languages. A format specifieris a string (thusenclosed in
quotation marks, as in the example above) that is constructed from 0 or more elements in the following
order:

[[fill]align][sign][#][0][width][.precision][type]

where:

Option Meaning
A fill character, which can be any character other than '}'. If a fillcharacteris specified,
fill
thenthenextcharactermustbeoneofthealignmentoptions.

Option Meaning
'<' Leftaligned(default)
align '>' Rightaligned(asinourexample)
'=' Putpaddingafterthesign,ifany,butbeforethefirstdigit.
'^' Centeraligned


Option Meaning
'+' Useasignforbothpositiveandnegativenumbers.
sign '' Onlyuseasignfornegativenumbers.(Thisisthedefaultbehaviour.)
Use a leading space on positive numbers and a minus sign on
space
negativenumbers

Onlyforintegersinbinary,octalorhexadecimaloutput.Prefixestheoutputby '0b', 'O0', or
#
'0x'respectively
0 Padtheoutputwithazero.
width Minimumfieldwidth.Ifnotspecified,thenthefieldwidthisdeterminedbythecontent
Number of digits to be displayed after the decimal point, for floating pointnumbers.Not
precision
validforintegers.Fornonnumbers,itindicatesthemaximumfieldwidth.

Option Meaning
's' Stringformat.Thisisthedefaultforstringvaluesandmaybeomitted
type
'b' Binary.Formatsanumberinbase2
'd' Decimal.Formatsanumberinbase10
'o' Octal.Formatsanumberinbase8

Hexadecimal.Formatsanumberinbase16,usinglowercaseletters
'x'
forthedigitsabove9
Hexadecimal. Formats a number in base 16, using uppercase
'X'
lettersforthedigitsabove9
Number. This is the same as'd' but inserts separatorsaccording to
'n'
thelocale.
'e' Exponentnotation.Uses'e'toindicatetheexponent.
'E' Exponentnotation.Uses'E'toindicatetheexponent.
'f'
or
Fixedpoint
'F'
General format. Prints in either fixed point or scientific format
'g'
or dependingon the thevalueandthespecifiedfieldwidth.Lowercase
'G' 'g' uses lowercase 'e' for scientific notation. Upper case 'G' uses
uppercase'E'forscientificnotation.
Percentage. Multiplies by 100, displays in fixed ('f') format and
'%'
appendsapercentsign.

Whew!There are lots of waystoformat the data.Youcanusetheformat()methodofthe stringdatatype


toperformvariable substitutionand formatting onmanyitemsat once.Returningtoourexample,wecould
doitthisway:

>>>foriinrange(2,12,2):#range()willmakealiststarting at2,endingat
11andincrementingby2
...print"Thesquareof{0:>3d}is{1:>3d}".format(i,i**2)
...
Thesquareof2is4
Thesquareof4is16
Thesquareof6is36
Thesquareof8is64
Thesquareof10is100
>>>

Let us look at the differences in the print statement. First, there isjust onestring, which embedssome
formatting instructions. This is followed by a period ('.') and the format function call, with arguments
corresponding to the values we want to format and insert into the string for printing. Let's dissect the
formattinginstructions. Aformatstringcontains"replacementfields"surroundedbybraces(the characters{
and}).Anything not insidebracesis copied asistotheoutput. (Ifyouneed abraceintheoutput,include
theminpairs:{{and}}.)

Insidethebraces,thereplacementfieldisbuiltupasfollows:

field[!conversion][:format]

where "field" is either a field nameor number. Our exampleuses numbers, which simply means that the
value for a field isthecorrespondingargumentsupplied totheformatmethod,countingfromzero.Thefield
name may also, optionally, include a subscript forlists andtuples, keysformappingobjects (discussed in
Chapter 4)andattributesforclassinstances(discussedinChapter6)."conversion"isforspecialcasesand
normally not required it may either be "r" or "s". (See the official documentation for more details.) The
"format" is the format specificationwe justdiscussed.Herearesome alternatewaysto printthelinesinour
example,showingsomeofthewaysyoucanspecifythefield:

print "The square of {integer:>3d} is {square:>3d}".format(integer=i,


square=i**2)

print"Thesquareof{0[0]:>3d}is{0[1]:>3d}".format([i,i**2])

3.3TheStandardLibrary

The Pythonstandard libraryis organizedinto modules,with eachmodulecontaining manyfunctionsfor use


in a specificarea. Thereareabout 250modules in the standardlibrary atthemoment.Someyouwilluse
right away. Others you may never use, if your work never touches on the domains covered by those
modules.Let'sstartoffbylookingatoneofthemostusedmodules:math!

3.3.1Themathmodule

If we want to use the math module, we need to tell Python to go and get it. We do that using the
importstatement.OpenupaninteractivePythonsessionandtype:

>>>importmath#Importthemathmodule

Nowthatwehaveimportedthemathmodule,wecanusethesinfunction:

>>>math.sin(1)
0.8414709848078965

This statementsays,"Lookup the functioncalled'sin' in the module 'math',then call that functionwiththe
value '1' andreturntheresults." Thatis exactlywhathappened.(Ifyouareskeptical,goahead andlookup
the value of sine(1) in a table of sines.) The math moduleprovides 18 trigonometricfunctions, six power
andlogarithm functions,12 functions from number theory andtwoimportantconstants.Trythesefunctions
onyourcomputer:

Function name and


Purpose Example
arguments
>>>math.factorial(10)
math.factorial(x) returnsxfactorial
3628800
returnsthesmallestinteger >>>math.ceil(3.5)
math.ceil(x)
greaterthanorequaltox 4.0
>>>math.sqrt(10)
math.sqrt(x) returnsthesquarerootofx
3.1622776601683795
convertsanglexfromdegrees >>>math.radians(60)
math.radians(x)
toradians 1.0471975511965976
convertsanglexfromradians >>>math.degrees(2)
math.degrees(x)
todegrees 114.59155902616465
>>>math.pi
3.1415926535897931
math.pi themathematicalconstantpi
>>>math.degrees(math.pi)
180.0

3.3.2TheOSModule

The OS module contains a number of functions that can be used to query the operating system for
information about the running process (where Python is running),to manipulate files,toissue commands
andformanyother,osspecific purposes. We will cover just afewexamplesthatencourageyouto consult
the official documentation for a complete list of available functions and howtousethem. Letusstart by
importingthemodule:

>>>importos
Now,let'strysomesimplequeries:

>>>os.access('my.txt',os.F_OK)#Seeifwecanaccessafile
True
>>>os.rename('my.txt','your.txt')#Renamethefile
>>>os.access('my.txt',os.F_OK)#Seeifwecanstillaccessthefile
False
>>>os.getenv('HOME')#RetrievetheenvironmentvariableHOME
'/home/user1'
>>>os.getcwd()#Findthecurrentworkingdirectory
'/home/user1'
>>>temp_file=os.tmpfile()#Openatemporaryfileforwriting
>>>os.system('unamea')#Issueasystemcommand
Linuxubuntu2.6.3120generic#58UbuntuSMPFriMar1205:23:09UTC2010i686
GNU/Linux

Trythesefunctionsonyourowncomputer(someareplatformspecific):

Functionnameandarguments Purpose
Returnsthenameofthecurrently
os.getlogin()
loggedinuser.
Createadirectorywiththesupplied
os.mkdir(path)
pathname.
Removeadirectorywiththespecified
os.rmdir(path)
pathname.
os.chdir(path) Changethecurrentworkingdirectory.
Returnalistofthenamesofthefilesin
os.listdir(path)
thespecifiedpath.

3.3.3ThePlatformModule

The platformmoduleprovidesaccess toidentificationinformationforthesystemonwhichPython isrunning.


Atthetime ofwriting, itincluded17functionsthatareplatformgeneric(availableonallsupportedplatforms)
andanothersevenforspecificplatforms.Forexample:

>>>importplatform
>>>platform.architecture()
('32bit','ELF')
>>>platform.machine()
'i686'
>>>platform.node()
'ubuntu'
>>>platform.platform()
'Linux2.6.3120generici686withUbuntu9.10karmic'
>>>platform.python_version()
'2.6.4'
>>>platform.system()
'Linux'
>>>platform.uname()
('Linux','ubuntu','2.6.3120generic','#58UbuntuSMPFriMar1205:23:09
UTC2010','i686','')
>>>

Tryeachofthese on your own system andobservetheresults.IfyouarerunninganyversionofWindows,


trytheplatform.win32_ver()functionaswell.

3.3.4Thesysmodule

This module provides access to some Python interpreter variables and to certain functions that are
closelyaligned with the interpreter's operation. Here area few examplesfromtheavailable 70+ functions
andvariables:

$pythonia=1b=2c="foo"
Python2.6.4(r264:75706,Dec72009,18:45:15)
[GCC4.4.1]onlinux2
Type"help","copyright","credits"or"license"formoreinformation.
>>>importsys
>>>sys.argv#Listofcommandlinearguments
['','a=1','b=2','c=foo']
>>>sys.maxint#Largestsupportedinteger
2147483647
>>>sys.maxsize#Largestobjectsize
2147483647
>>>sys.platform#Platformwe'rerunningon
'linux2'
>>>sys.version#VersionofPython(comparetoplatform.python_version())
'2.6.4(r264:75706,Dec72009,18:45:15)\n[GCC4.4.1]'

Tryeachoftheseonyoursystemandobservetheresults.Someotherfunctionstotry:

Function Purpose
sys.builtin_module_ Tuple of the names of the modules compiled with your
names versionofPython
sys.copyright Pythoncopyrightstatement
sys.getwindowsversi
Windowsonly:versioninformation
on()
sys.modules Dictionarymappingmodulenamestoloadedmodules
sys.path Listofpathstosearchformodules
sys.winver VersionnumberusedforregistrykeysonWindows

3.4UserDefinedFunctions

3.4.1Basics

Having justsurveyed afewofthemodulesin the standardlibrary andknowing that thereare 240ormore


modules that we haven't even consideredyou might wonder if you would even need to define your own
not
functions.As itturnsout, there area few serious applicationsthatyou willbuildthatwill requireyouto
write your own functions if only to make your programs more manageable and readable. Fortunately,
writingfunctionsisnotdifficult.Thebasictemplateforafunctionisasfollows:

deffunction_name(arg1,arg2,...,keyword_arg1=default,keyword_arg2=default):
"""
documentationstringdescribingthepurposeofthefunction,
whatitsinputargumentsareandwhatitreturns
"""
#bodyoffunction
returnreturned_data

Let us look at each of these pieces in turn. Every function definition begins with the word "def",that is
followed by the name of the function. Quoting from PEP8, "Function names should be lowercase, with
wordsseparatedbyunderscoresasnecessarytoimprovereadability."

Function names should be lowercase, with words


separated
byunderscoresasnecessarytoimprovereadability.

After the function name, with nointervening whitespace, comes a list of the argumentsthat yourfunction
will use,enclosedinparentheses.Firstcomethepositionalargument names, then the keywordargument
nameswithdefaultvalues.Notethatyoucannotminglethepositionalandkeywordarguments.

Immediately followingthe"def" statement should come a documentationstring explainingwhat the function


is for. It should include the inputarguments,ifanyanddescribewhat dataisreturned,ifany.Itis indented
fourspaces.

Followingthedocstringcomes the body of the function, indented fourspacesfromthedocstring.Ifdatais


tobereturnedtothecallerofthefunction,thereshouldbea"return"statementthatdoesjustthat.

Nowthatweunderstandthebasicformat,let'swriteasimplefunctionthatcomputesaFibonaccinumber:

>>>deffibonacci(n):
..."""
...Computesthen'thFibonaccinumber
...
...Inputargument:naninteger
...Returns:then'thFibonaccinumber
..."""

...
...ifn==0:
...return0
...elifn==1:
...return1
...else:
...returnfibonacci(n1)+fibonacci(n2)
...

Copy this function definition (stripping out the '>>> ' and '... 'fromthe beginning of the lines) and try this
function inan interactive Pythonsession. It shouldreturntheresult foranyFibonacci number uptoabout
1000, though itwillgetslower as the numbersgetbigger.To understand why, wehave tofirstlookat the
last line of the function. The "return"statement calls the fibonacci() function twice. This is called
recursion and is aquitecommonapproachforsolvingcertainrepetitiveproblems. However,it isnotagood
approach for this problem, since the overheadofusingrecursion makesthe runningtimestretch out asthe
input numbersincrease withnoendinsight!Actually,there willbeastoppingpoint.Python has abuiltin
limit for how deeprecursive calls may go. You can access that depth using the function
sys.getrecursionlimit().

>>>importsys
>>>sys.getrecursionlimit()
1000
>>>

In this case, the limit is 1000, which means that it should be impossible to ask for fibonacci(1002).
Practically, you would notwant to,since it may takehours to computethis way!SeeExercise 3.5.1 for a
constanttimeapproachtothisproblem.Meanwhile,let'sseeifwecandoitwithoutrecursioninlineartime:

>>>deffibonacci(n):
..."""
...Computesthen'thFibonaccinumberinlineartime.
...
...Inputargument:naninteger
...Returns:then'thFibonaccinumber
..."""
...
...ifn==0:
...return0
...fc=fn=1
...for_inxrange(2,n):
...fn,fc=fn+fc,fn
...returnfn

Therearesome thingsinthis examplethatwehaven't discussedbefore.Firstof all,itispermittedinPython


tochainassignments,whichiswhytheline:

fc=fn=1

causes both fc and fn tobe initializedtothevalue1.Second, the forloop usesthexrange() function.This


function works similarly to the range() functiondiscussed earlier, but servesup the numbersoneata time,
rather than in a list, which saves memory and processing time. (Computer scientists call that lazy
evaluation.) Also notice thattheloop uses'_' asavariablename.Thisisacommonpracticewhenwedon't
needthevariable foranythingelse. Inthiscase, it isonlyusedtorunthemechanicsoftheloop.Thethird
newideaistheassignmentstatementinthebodyoftheloop:

fn,fc=fn+fc,fn

This assignment statement assigns two values totwovariables.Also,becauseofthewayPythonexecutes


statements like this, you can usethesamevariableson the left and ontheright sides of the assignment.
You can do so without worrying about the execution order. It works as if there wereinvisibletemporary
variables tohold the intermediate values(which is notfarfromthetruth).Withthisnew, improvedfunction,
youshould beable tocalculateanyFibonaccinumberup tothe limitsofyourmachinearchitecture.(Infact,
youmightrunoutofmemoryifyoutrysomereallylargevalues.)

Thereis one otherthingwe shoulddo with our function. We need to check ourinput argument tobesure
that it is valid. It needs to be a nonnegative integer. To check this, we can use the builtin function
isinstance()likethis:
isinstance(n,int)#ReturnTrueifnisaninteger

Usingthis,beforewebeginanycalculations,wewilladdthefollowingtesttoourfunction:

ifnotisinstance(n,int)orn<0:
raiseValueError,"Argumentmustbeaninteger>=0"

This statementalso introduces the "raise"command, which causesan exceptiontoberaised("ValueError"


in this case) toalert the caller that the functionwascalledwithan invalid argument.Pythoncomes with a
numberofbuiltinexceptionsandyoucanalsodefineyour owniftheneedarises.Asanexercise,insertthe
"if"statementaboveintothelinearversionofthefunctionandtestitwithvariousinvalidvalues.

Sooneror later, itis likely thatyouwillneedtowrite a functionthat needstoprocess a variablenumberof


arguments. In fact, the stringmethod format()isan example of suchafunction.Thatmeansthatthatyou
cannot listallofthearguments when you definethefunction.So, howdoes the format()methoddoitand
howshould you?Theanswerlies in the use of the"*identifier"and "**identifier"forms.Anexampleofsuch
asusewouldbe:

defvar_func(*args,**kwargs):
<suite>

This function takes in an unknown number of positional arguments followed by an unknown number of
keywordarguments.Let'sseethisinaction:

>>>deffunc(*args,**kwargs):
...print"Args:",args
...print"Keywordargs:",kwargs

...
>>>
>>>func(1,2,3,a=4,b=5,c=6)
Args:(1,2,3)
Keywordargs:{'a':4,'c':6,'b':5}
>>>func()
Args:()
Keywordargs:{}

As you can see,thepositionalarguments areinsertedintoatuple.Thiscanbeaccessedthroughthesame


name as in the functiondefinition.Similarly,the keyword argumentsareinsertedintoadictionary(covered
inChapter4)whichyoucanaccessusingthedictionarymethodscoveredinChapter4.

3.4.2GeneratorsandGeneratorExpressions

InSection 3.4.1 wementioned that a functionmust include a return statement if it istoreturnsomethingto


the caller. That's not quite true. There is another statementthat will dothatas well: yield.However,the
presence of this statement turns the function into something special: a generator. A generator is a
producer ofinformation.

Let'sseehowthismightworkwithourFibonaccifunction:

>>>deffibonacci_generator(n=0):
..."""
...YieldsFibonaccinumbersfrom0ton
...
...Inputargument:naninteger,thehighestFibonaccinumbertobe
generated
...Yields:Fibonaccinumbersfrom0ton,inclusive
..."""
...
...ifnotisinstance(n,int)orn<0:
...raiseValueError,"Argumentmustbeaninteger>=0"
...
...yield0
...ifn==0:
...return
...yield1
...fc=fn=1
...for_inxrange(2,n):
...fn,fc=fn+fc,fn
...yieldfn

Now,let'susethisgenerator:

>>>fib_nums=fibonacci_generator(10)
>>>forfinfib_nums:
...printf

...
0
1
2
3
5
8
13
21
34
55
>>>

What is going on here? First of all, let us see how we changed our fibonacci() function into our new
fibonacci_generator() function. For starters, we added a default value for n, so that we can call our
generatorwithoutanyarguments andgetthe firstFibonaccinumber. Next, weadded a yield statementto
sendthefirstFibonaccinumber, 0,backtothecaller.Then,assumingthat thecallerwantsmoreresults,we
added a secondyieldstatement to send the second Fibonacci number,1. Finally, in the bodyof theloop,
everytime wecalculate a new number,weusetheyieldstatementto sendthenextFibonaccinumberback
tothecaller. At compile time, when Python sees ayieldstatementinafunction,itmarksthatfunctionasa
generator. At execution time, when a yield statement is encountered, the result of the yieldstatementis
sent back to the caller andexecution issuspended.Thenext time the caller calls,thefunction continues
until it hits anotheryieldstatement, and so on, until no moreyieldstatements are encountered and the
functionexits.

Whenweuseourgenerator,thefirststatementis:

>>>fib_nums=fibonacci_generator(10)

merely establishes a reference to ourgenerator,butdoesnotstartexecutingit.Then,themechanics ofthe


forloop repeatedly calls a special method of the loop expression, next()(that is, in our example,
fib_nums.next())untilthegeneratorexits.

Thereis also another specialgenerator method, close()thatwe can use toforceageneratortostop.Here


isanexampleofitinaction:
>>>fib_nums=fibonacci_generator(10)
>>>forfinfib_nums:
...printf
...iff>5:
...fib_nums.close()
...
0
1
2
3
5
8
>>>

Python also supports a sortof inline generator, called a generator expression . It is useful for simple
generators that can be written as a single expression. For example, suppose you wanted to produce
squaresofintegers.Ageneratorexpressionlikethiswoulddothetrick:

>>>importsys
>>>sys.maxint
9223372036854775807
>>>squares=(i**2foriinxrange(sys.maxint))#Generatorexpression
yieldingsquares
>>>forsinsquares:
...prints
...ifs>100:
...squares.close()
...
0
1
4
9
16
25

Noticethat the generator expression looks verymuchlikea listcomprehension,exceptthatitisenclosedin


parentheses instead of in brackets. Thatis how Python recognizes that this isagenerator expressionand
why we cannot use parentheses in thisfashion as a tuplecomprehension. Inthisexample,we madethe
upper limit the same as the maximum integer value for the system running the generator, yet we only
generate one square at at time. In fact, if you change the parentheses to brackets, you will
have a list
comprehension,butonesobigthatitmaynotfitinyourcomputer'smemory.Trythatatyourownrisk!

Note: Instead of xrange(sys.maxint)we couldhaveusedafunctionfromtheitertoolsmodulecalledcount().


The count()functionstarts(bydefault)atzero, andcounts forever.Oursimplifiedgeneratorwouldthenlook
likethis:
>>>fromitertoolsimportcount
>>>squares=(i**2foriincount())
>>>

Thisexamplealsoshowsthewaytoimportasinglefunctionfromamodule.

3.4.3Closures

Sometimes youfindthatyou willuse thesame functionover andover again,usingsome butnotallof the


same arguments each time. Consider the pow() builtin function. If you enterhelp(pow)inan interactive
Pythonsession,youwillseesomethinglikethis:

pow(...)
pow(x,y[,z])>number

Withtwoarguments,equivalenttox**y.Withthreearguments,
equivalentto(x**y)%z,butmaybemoreefficient(e.g.forlongs).

Now, suppose you wanted to use the threeargument form, but for your application, the lastargument is
always3. Itwouldbenicenotto havetoenter3everytimeyoucallthis function.Aclosurewouldallowyou
closing
do to this, by the value for z so that you didn't have to write it again and again. Such aclosure
wouldlooklike:

>>>defpow3(x,y):
...returnpow(x,y,3)
...

Oncedefined,wecanuseournewfunction:

>>>pow3(3,4)
0
>>>pow3(5,4)
1
>>>pow3(5,7)
2

Let'slookatanexampleofaclosurewithauserdefinedfunction:
>>>deff(x):
...defg(y):
...returnx>y
...returng
...
>>>lt5=f(5)
>>>lt5(4)
True
>>>lt5(6)
False
>>>

Noticehowwe defineda functionwithinan outer function, used avaluefromtheouterfunctionintheinner


function, andthen returned areferenceto thejustdefinedinnerfunction.Thisisaclosure thatencloses the
value for x.Thus, when we use ournewfunction to define thefunction lt5(), wegeta customfunction that
testsforvalueslessthan5.Similarlywecoulddefinelt6,lt7,etc.

Closures can often reducetheamount of code you have to write, ifyouneedseveralsimilarfunctionsthat


differin onlya few arguments. You mightbe wondering why,if closuresaresouseful,thereisnotalibrary
functiontomakethemeasytobuild.Well,thereis!Itisthefunctionpartialinthemodulefunctools:

>>>fromfunctoolsimportpartial
>>>base2=partial(int,base=2)
>>>base2('101010')#Convertstringinbase2toaninteger
42
>>>

The partial function works with any function that has keyword arguments. If you want to
close (that is,
freeze or lockin) positional arguments, theymustbe done in the orderinwhich theyoccur inthefunction
definition.Forexample:

>>>pow4=partial(pow,4)#Functiontoraise4toanypower
>>>pow4(2)#Compute4tothepowerof2(4squared)
16
>>>

Naturally,youcanusepartialwithuserdefinedfunctionsaswellaslibraryfunctions.

3.4.4Decorators

Sometimes youhave a function, or acollection ofsimilarfunctions, thatdoalmosteverythingthatyouwant.


There's justone or two thingsyouwouldlike to addtoreachyour goal.Thisiswhere
decoratorscomein.
A decorator takes a function as an argument, adds something extra, then returns a new function that
combinestheoriginalfunction with the extra abilities. Thinkaboutabirthdaycake.Youfirstbake thecake
which is probably delicious on its own, then you make icing and decoratethecake with the icing.You
mightevengo further anduseacontrasting coloricing to write"HappyBirthday" onthecake.That isjust
thekindofthingfunctiondecoratorsdo.Let'slookatasimpleexample:

>>>defdecorator(f):
...def_f(x):
...print"I'minf,calling",f,"withargument",x
...returnf(x)
...return_f
...
>>>@decorator
...defg(x):
...print"I'mingwithargument",x
...
>>>g(42)
I'minf,calling<functiongat0x033D7970>withargument2
I'mingwithargument42

First,we definedadecoratorfunction,whichtakesinjustoneargument,which isafunctionto bedecorated.


Within the decorator function,we definea second,nestedfunction.(If youthink thislooks like aclosure,
you'reright!Decorators arebased onthesameidea,butgenerallyadecoratortakesjustoneargument:a
function reference.) The nested functionsimplyreports which function it iscallingandwith whatargument.
Then,itcallsthetargetfunction.Finally,themaindecoratorfunctionreturnstheinnerfunctionasitsresult.

Having defined the decorator function, weuseit in the definition of our nextfunction.Toto that,weusea
special statement that begins withan '@'then continueswiththe name ofthedecoratorfunction. Ineffect,
we'reputtingicing onthecake! Finally,we defineour realfunction. However, notice whathappens when
wecall the realfunction. First, wegettheline printedfromthedecoratorfunction,thenthelineprintedfrom
therealfunction.Thisisthedecoratorinaction.

Let's take a look at a more complicated example. This is also a great opportunity to introduce Python's
exceptionhandling facilities. Say that you have a series of functions that read from a database. Each
function takes inthename of the databaseand executessomespecialreadoperation. Askeletonofsuch
afunctionmightlooklikethis:

defdbread1(dbname):
"""
Doreadtype1fromdatabasedbname
"""
data=dbname.read(...)#Callthedatabasereadfunction
returndata

Now,supposeyouwanttobeabletoseeerrorsthat occurinthefunctiondbname.read().Supposethat that


function may raise errors DBERR1andDBERR2.Youwanttoreporttheerrorstotheuserinsomefashion
for further analysis and do not want the user to just seecryptic errormessages from the database itself.
Youcandefineadecoratorthatyoucanuseforallyourdbread()functionsthatusesthePythontry...except
syntaxtocatchtheexceptions.Itmightlooklikethis:

defcatch_errors(func):
def_try(dbname):
try:
returnfunc(dbname)
exceptDBERR1,msg:
print"Databaseerror1:",msg
raise
exceptDBERR2,msg:
print"Databaseerror2:",msg
raise
except:
print"Unknowndatabaseerroroccurred"
raise
else:
#Databasefunctioncompletednormally
finally:
#Performanyneededcleanup
return_try

The inner function, _try(), wraps the calltothe databasefunction inatry...except structure.First,theactual
function call func(dbname) is attempted. Then, if either DBERR1or DBERR2occurs,theexceptclauses
matching those two exceptions report on the error. If an unknown exception is encountered, the third
exceptclause catches it (so it is the default error handler). If nothing goes wrong, the code in the
elseclause is executed.No matterwhat happens,thecodeinthefinally clauseisexecutedattheend(any
cleanupcodeshouldgohere).

Now thatwe have our decorator ready, wecanuseit to wrap any ofourdatabasefunctions andknow that
theerrorswillbecaughtandhandled.Wejusthavetowritethemlikethis:

@catch_errors
defdbread1(dbname):
...
@catch_errors
defdbread2(dbname):

...

.
.
.
In case you're wondering, it is perfectly legal to stack decorators, which means this would be valid
(assumingyouhavepreviouslydefinedthedecoratorfunctions):

@happy_birthday
@icing
@top_layer
@filling
@bottom_layer
defplate(shape):
...

3.4.5CoroutinesandConsumers

If generators aredataproducers,coroutinesaredataconsumers.Coroutinesstart offlifelookingalotlike


generators.Thedifferenceisinhowyieldisused.Here'sanexampleofacoroutinethatconsumesdata:

>>>defco_routine(path):
...f=open(path,'w')
...try:
...whileTrue:
...data=yield#yieldexpression
...f.write(data+'\n')
...exceptGeneratorExit:
...f.close()
...
>>>f=co_routine("new.file")
>>>f.send(None)
>>>f.send('a')
>>>f.send('b')
>>>f.send('c')
>>>f.close()
>>>
>>>nf=open("new.file")
>>>forlineinnf:
...printline,
...
a
b
c
>>>nf.close()

(Admittedly, this coroutine does not do anything special. It just writes lines to a file specified when itis
called. This could have been done withoutanything fancy,butitshouldservetoshowhowcoroutineswork

asdataconsumersandwillhopefullyinspireyoutofindmore(andbetter!)usesforthisapproach.)
The coroutine startsoff likeanyother function,declaring its nameandsingleargument.Thenitopensthe
file to be written. Next, it enters a try...except construct, which begins with a whileloop. The loop is
designed to run forever, or until an exception is raised. The single except statement looks for one
exception:GeneratorExit.

Inthemain program code,thecoroutineis called withthepathname "new.file".Recallfromourdiscussion


about generators(which acoroutineis,sinceitcontains ayield),thatitwon't startexecuting untilitisasked
for data, atwhichtimeitwilladvancetothefirstyieldinthefunction.Thenextlineis peculiar:f.send(None).
What this statementdoes, isthat it causes the coroutine tostart executingup to the first yield. Thus,the
file is opened, the whileloop is entered and the function hits the first yield. Contrary to our generators,
though, the yieldis ontherighthandsideofanassignmentthatis,itisactually an expression !Morethan
that, itcanconsume dataas wellasproduceit .So, when the yieldis encounteredforthefirsttime,itfirst
produces data (nothing, in this case), then if reached via the send() method waitsfordata from the
caller.

The nextthree lines send three piecesof datatothecoroutine, which completestheyield expressionand
assigns the resulttothevariable data, which isthen written to the file.Finally, the statement f.close()tells
the coroutine to stop, just like it would for a generator. Internally, it raises theexceptionGeneratorExit,
whichiscaughtbyourexceptclause.Theexceptclausejustclosesthefileandthecoroutineends.

3.5LambdaExpressions

Lambdaexpressionsareawayofcreatinganonymousfunctions.Heresasimpleone:

>>>lambdax:x*x

Ifyouguessedthatthatsimplysquaresagivennumber,youdbecorrect.Infact,wecantake
thissimpleexpressionandassignittosomevariable:

>>>square=lambdax:x*x

whichisexactlythesameasdefininga square functionlikethis:

>>>defsquare(x):
returnx*x

Sowhat?youmayask.Isavealittleontyping,bigdeal!Well,therearegreatusesfor
lambdaexpressions.Forexample,somefunctionstakefunctionsasarguments.Rememberthe
partial() function?However,usingalambdawithapartialisnoeasierthandefiningthe
functioninthefirstplace!

OneofthemethodsyoucanusewithPythonlistsisthe sort(). Thismethodhasanoptional


firstargumentthatisyouguessedit!afunction.SoIcanwrite:

>>>mylist.sort(lambdax,y:cmp(y,x))

cmp isabuiltinfunctionthatcomparestwoobjects.Hereweusealambdainplaceofa
previouslydefinedfunctiontoperhapschangethesortorderbasedonsomeruleofourown.
(Intheexample,therulewouldcausethelisttobesortedindescendingorder.)

LambdasalsohavegreatapplicationswhenwritingGUIprogramswherethingshappen
asynchronously.(Thisisalargetopicthatisoutofscopeforthisintroductoryvolume.)

Lambdasareagreattooltohaveinyourkit!

3.6Exercises

1.Fibonaccinumbersinconstanttime


(a)ThestandarddefinitionoftheFibonaccisequenceisrecursive:

It can beshown,however, that thereis a closed (i.e.nonrecursive)formula (Binet's formula, after French
mathematician Jacques Philippe Marie Binet, 17861856) for the sequence that is based on the
"goldenratio."Usingthatformulaanddoingalittlealgebra,itcanbereducedtothis:

where isthegoldenratio:

Write a function thatcomputes then'thFibonaccinumberusing thisformula.Notethatyourfunctionshould


have noloopsinitand from that perspective itcanbesaidtohavea constantcomplexityorO(1)using"big
O"notation.

(b) Thereis a modulein the standardlibrary called


timeit
that can beused to time snippets ofcode.
Youcanuseitlikethis:

>>>fromtimeitimportTimer
>>>deffibonacci(n):
..."""
...Computesthen'thFibonaccinumberinlineartime.
...
...Inputargument:naninteger
...Returns:then'thFibonaccinumber
..."""
...
...ifn==0:
...return0
...fc=fn=1
...for_inxrange(2,n):
...fn,fc=fn+fc,fn
...returnfn
...
>>>Timer('fibonacci(10)','from__main__importfibonacci').timeit()

2.3244328498840332
>>>

By default,thetimeit() methodruns the sample code 1,000,000 (yes, one million)timesandreportson the
total time takenin seconds. For this exercise, use thetimeit moduletotime yournewfunctionfrompart(a)
and compare it to the times for the sameFibonacci numbersusing the above function.As the Fibonacci
numbers increase, which implementation(the given oneoryournew "constanttime"version),producesthe
fastestresult?Dotheybothproducethesameresultsforallvaluesofnupto100?Ifnot,whynot?

2.Decoratortohelpsetupacoroutineandautomaticallyadvancetofirstyield.

Recallthatacoroutinebuiltusing yield expressionsdoesnotstartuntil thefirst next() or


send(None)
call isreceived.However,itisalltooeasy toforgetto dothatsetupcallbeforeusingthecoroutine.Writea
function decorator that can be used to automate the first call to advance the coroutine to the first yield
statement.Demonstratetheuseofyourdecoratoronthecoroutinefromsection3.4.5.

3.WriteageneratortolistallPythonfilesinthestandardlibrary
Recall that the
sys
module has a
pathattribute thatis a list of all paths thatPython will search to find
modules when processing an import statement. Depending on your operating system, the list may look
somethinglikethis:

>>>importsys
>>>sys.path
['','/usr/lib/python2.6','/usr/lib/python2.6/platlinux2',
'/usr/lib/python2.6/libtk',...]
>>>

Note the list itemthatcontains the path to the beginningof thePython library. (Inthe aboveexample,itis
sys.path[1] ).

In the OS module there is a function named walk that traverses the entire tree under a given starting
directory and returns a tuple for eachone that contains three items:thedirectorypath,thesubdirectories
containedinthatdirectoryandthefilenamescontainedinthatdirectory.

For thisexercise,write a generator thatuses these modules togenerate filenamesinthePythonstandard


library where the last three characters are ".py". (Hint, all Python strings have a method called
endswith() thatcanbeusedtocheckifthestringendswithsomesequenceofcharacters.)

4.ListMaintenance

(a)

Thereis a librarymodule named bisect that can be usedtoperform binarysearches onsortedlists
toquickly find items inthelist.Forexample,ifyou haveaPython listcalledmylist thatisalreadysorted,you
canfindaniteminthelistlikethis:

>>>frombisectimportbisect_left

>>>mylist=['abc','def','ghi','klm','opq','rst','uvw','xyz']
>>>bisect_left(mylist,'klm')
3
>>>mylist[3]
'klm'
>>>

Note that, for larger, sorted lists, bisection is substantially faster than the list method
index()
, which
searchesthelistsequentiallyfromthebeginning.

Write a function that uses bisection. The function must take three arguments: a list, an item and an
operation.Thefirstargumentcanbe any validPython list (make sure thatitis!)thesecondargumentcan
beanyitemthatmightbeinthelistthethirdparameterisanintegercodespecifyinganoperation:

Code Operation
0 Sortthelist.ReturnsNone.
Insert item into list using bisection. Returns True if
1 the new item is already in the list (but inserts a
duplicateanyway),otherwisereturnsFalse.
Remove itemfromlistusingbisection.ReturnsTrue
2
ifitemfound,otherwisereturnsFalse.
Returns True if item is in the list, otherwise return
4
False

Be sure to testyour functionon a wide variety of listsand items and operations, includingempty listsand
nullitems.(NotethatNoneisavalidvalue foralistitembutyouhave todecidewhetheryouwanttoinclude
itornot.)

(b) Write four closures for your function to make the four operationsusablewithout specifyingthe third
argument.

(c) Suppose that your program only operates on a single, large list. Use the partial function to create
closurestocallyournewfunctionsothatyoucanomitthefirstargument.

Chapter4Sequences,MappingsandCollections
4
So far we haveconsidered alimited subset of Pythondata types:integers,floatingpointnumbers, strings
and lists. In this chapter we will look at some of the other main Python data types and some of the
extensions built on top of them. These types fall into the categories of Sequences, Collections and
Mappings.

4.1Sequences

Sequencesareobjectsoverwhichitispossibletoiterate.Thatis,foreverysequencetype,thismustwork:

foriteminsequence:
#dosomethingwithitem

InChapter 3welookedatlists,whichareoneofthemostcommonlyusedPythonsequences. Wesawhow


to build lists, addandremove items,slicetheminto smaller listsand iterateoverthem. However,back in
Chapter2,weintroducedonecommonsequencetype,string.Nowwewilldiscussitinfurtherdetail.

4.2Morefunwithstrings
4.2.1Multilinestrings

So far, we know how to build strings. We simply enclose some charactersin quotation marks. Wealso
learntthattherearefourwaystodothis:

Singlequotationmarks,e.g.'stringinsinglequotationmarks'
Doublequotationmarks,e.g."stringindoublequotationmarks"
Triplesinglequotationmarks,e.g.'''stringintriplesinglequotationmarks'''
Tripledoublequotationmarks,e.g."""stringintripledoublequotationmarks"""

We also learned that tripledouble quotation marks are used to document functions (the docstring).
However the two "triple" forms have a more general purpose: multiline strings. They are very useful.
Suppose you wanted to write three lines to a file. If you usedeither of the firsttwoforms,youmight do
somethinglikethis:

>>>line1="firstline"#Stringforthefirstline
>>>line2="secondline"#Stringforthesecondline
>>>line3="thirdline"#Stringforthethirdline

>>>f=open("/tmp/3lines.txt",'w')#Openafiletowrite
>>>f.write(line1+'\n')#Writefirstline,appendinganewline
>>>f.write(line2+'\n')#Writesecondline,appendinganewline
>>>f.write(line3+'\n')#Writethirdline,appendinganewline
>>>f.close()#Closethefile
>>>

What if you then had to go back and add another threelines?You'd have to alsoaddthree new write()
calls.If youroutputfile grewand grew, then the maintenancewouldbecome boring at least, andlikelybe
errorprone aswell.Wouldn't it be nice ifyoucoulddefine the content in oneplaceand thenwrite itinon
operation?Well,ifyouuseamultilinestring,youcandojustthat:

>>>lines="""firstline
...secondline
...thirdline
..."""
>>>f=open("/tmp/3lines.txt",'w')
>>>f.write(lines)
>>>f.close()
>>>

A multiline string, like the one above, can bedefined in one place and maintainedon its own. The code
that actually writes the data need not change if the multiline string changes. Also, a multiline string
automaticallyaddsnewlinecommandsat theendofeachline,sothatwedonotneedto addthembyhand.
A multiline string can alsobe a handy way towrite datathat requires substitution andcanbe performed
withtheformat()methodfromChapter3:

>>>HTML="""
...<html>
...<head>
...<title>{title}</title>
...</head>
...</body>
...Thisiseasytodoin{lang}
...using{how}.
...</body>
...</html>
..."""
>>>f=open("/tmp/multi.html",'w')
>>>f.write(
...HTML.format(title="Funwithstrings",lang="Python",how="multiline
strings")
...)
>>>f.close()
>>>

Here, we have formatted a simple page of HTML, using a multiline string to define a template with
substitutionvariables,thenusingtheformat()methodonitto substituteforthethreevariables.Notethatwe

used all capitals for the identifier for the multiline string constant. This is a convention used in Python
programsfordefiningconstantsandispartofPEP8.

Constantsareusuallydeclaredonamoduleleveland
writteninallcapitalletterswithunderscoresseparating
words.ExamplesincludeMAX_OVERFLOWandTOTAL.

This approachcanbe veryhandy for dynamically generatingtextthat isactuallycodeinanotherlanguage.


Using a multiline stringand formatting,it iseasy to generate asegment of JavaScript,XML, SQL orany
otherlanguageatexecutiontime.

4.2.2OtherStringMethods

Strings have a numberofvery useful methodsthat you can use forquerying and modifyingstrings.Also,
someofthearithmetic operatorstake on newmeaningwithstrings.The table below shows someofthese
andgivetypicalusecasesforthem.Forafulllist,seetheofficialdocumentation.

Methodoroperator Purpose Example


>>>'a'+'b'
+ Concatenation
'ab
>>>'a'*5
* Multiplication
'aaaaa'
>>>'a'in'bac'
[not]in ReturnTrueifstring1[not]foundinstring2
True
>>>a='abcd'
>>>a[1]
'b'
>>>a[2:4]
indexorslice
[ ] Returnstringorslice
'cd'
>>>a='abcd'
>>>a[1]
'd'
>>>len("abcd")
len() Returnlengthofstring
4
>>>"the
Return a new string with the first letter
capitalize() string".capitalize()
capitalized
'Thestring"
>>>"string".center(10)
center(
width, Return string centered in a new string of
'string'
[pad]
) width
length paddedwithpad (defaultblank)
>>>
count(sub[,start[,Returns number of nonoverlapping >>>"aaabbcc".count('a')
end]]) sub
occurrencesof intherange
[start,end] 3

sub
find(sub[, start[,Returns index of startof inrange
[start, >>>"aaabbcc".find("bc")
end]]) end]
or1ifnotfound 4
Returns a copy of the string translated to >>>"HTML".lower()
lower()
lowercase 'html'
>>>'Guidovan
Splitsthestringat sep and returnsa3tuple
Rossum'.partition('van')
sep
partition( ) with the first part, the separator andthelast
('Guido','van','
part.
Rossum')
Splits the string using sepas a separator >>>sys.path[1].split('/')
sep
split([ [,
maxspl
and returns a list of words. Limits the split ['','usr','lib',
it
]])
maxsplit
by . 'python2.6']
Returns anew stringwith leadingandtrailing >>>"toowide
[chars]
strip( ) characters removed. chars defaults to a ".strip()
space 'toowide'

4.2.3Moreonlists

BackinChapter3weintroducedlistsandtuples.Thereismuchmoretosayabouttheseusefuldatatypes!

4.2.4Updatinganddeletinglistitems

It'seasytoupdateanddeleteitemsinalist:

>>>delmylist[1]#removetheseconditemfromthelist

>>>mylist[1]="was"#changethevalueoftheseconditemto"was"

>>>delmylist[:]#emptythelist

Inthelast example,note thatif the beginningand/orend ofasliceisnotspecified,aslicebeginsatitem0,


the firstitem,andendsafterthelastitem. Thus,asliceof[:] referstothewholelist,asliceof[1:]meansthe
slicefromtheseconditemtotheendandaslice[:1]meanseverythingbutthelastitem.

4.2.5Operatorsandmethodsforlistsandtuples

Pythonlistsandtuplescomewithseveralusefulmethods,whichwelisthere:

Method Purpose Example

>>>[1,2,3]+[4,5,6]
+ Additemsfromanotherlist
[1,2,3,4,5,6]
>>>['foo']*3
* Duplicatelistitems
['foo','foo','foo']
append(x) Additemxtotheendofthelist mylist.append("example")

Count the number of items


count(x) mylist.count("list")
matchingx

Extend the list by addingtheitems


extend(x) mylist.extend(["more","items"])
fromthelistxtotheend

Return the index numberofitemx,


index(x) mylist.index("list")
iffoundinthelist

Remove and return itematindex x mylist.pop(0) # remove andreturn


pop(x)
(defaultlast) item0

Remove the first occurrence of


remove(x) mylist.remove("list")
itemwiththevaluex

Reverse the order of the items in


reverse() mylist.reverse()
thelist

Sorttheitemsin the list,optionally


sort(key=None,reverse=False) using the key function"key"and/or mylist.sort()
inreverseorder

Since tuples are immutable, the only methods available are count() andindex().Both operators are
available for tuples.Inaddition,since itis immutable, anewtuplewillbe created, rather than changing the
currentone.

4.3Sets

4.3.1IntroductiontoPythonSets

Sets in Python are used to implement the mathematical concept of a set. That is, they are unordered
collectionsof immutable objects. Sincetheyareunordered,theycannotbeindexed.Howeveritispossible

toiterateover them.To build a set, weusetheset()builtin function, which takes aniterableasit'ssingle,


optionalargument.Forexample:

>>>myset=set([1,2,3,4,5,4,3,2,1])
>>>myset
set([1,2,3,4,5])
>>>myset2={7,8,9} #shorthandsetdefinition
>>>myset2
set([8,9,7])

Noticethat the setcontains only unique objects. The extralistentriesthat wesupplied ([4,3,2,1])werenot
addedtothesetsincetheywerealreadypresent.Alsonoticethatthereisnoordertomembersofaset.

4.3.2Setoperations

Sets support the typical operations ofunion, intersectionanddifference,usingtheoperators"|","&"and"",


respectively. Also available isthesymmetric difference operator"^",whichreturnsanewsetwithelements
thatareinonesetortheother,butnotboth.Forexample:

>>>myset2={iforiinxrange(4,8)} #useacomprehension
>>>myset
set([1,2,3,4,5])
>>>myset|myset2#Union
set([1,2,3,4,5,6,7])
>>>myset&myset2#Intersection
set([4,5])
>>>mysetmyset2#Difference
set([1,2,3])
>>>myset^myset2#Symmetricdifference
set([1,2,3,6,7])

4.3.3SetTesting

Also available are the typical Boolean set operations for testing set memberships and the (proper)
subset/supersetoperations:

>>>myset
set([1,2,3,4,5])
>>>myset2
set([4,5,6,7])
>>>myset3=set([1,2,3])
>>>1inmyset#Setmembership
True
>>>6inmyset#Setmembership
False
>>>4notinmyset3#Setmembership
True
>>>myset3<myset#Propersubset

True
>>>myset<myset#Propersubset
False
>>>myset3<=myset#Subset
True
>>>myset>myset3#Propersuperset
True
>>>mset>=myset3#Superset
True
>>>myset>=myset2#Superset
False
>>>

Wesummarizetheseoperatorsinthistable:

Python
Setoperation
operator

&

in

notin

<

<=

>

>=

len(x)

4.3.4Setsasrelations

Sets arehandyforquicktestingofmembershipsand forremovingduplicatesfromalistortupleoranyother


iterables. Since members of a set can also be tuples, they can be used to represent relations as in a
relationaldatabaseandevenperformrelation algebraorSQLlikequeries. Forexample,let'sgenerateaset
oftuplesusingalibraryfunctionthatgeneratesrandomnumbers:

>>>fromrandomimportrandint
>>>R=set(
...(randint(1,10),randint(1,10),randint(1,10))
...for_inrange(100)
...)

Noticethat we used a comprehension in thecall to set().Such comprehensions can beusedwherever


iterables arecalledfor.It isofcouse possible tobuild Rwithout using a comprehension.Thecodewould
looksomethinglikethis:

>>>R=set()
>>>for_inrange(100):
...R.add(
...(randint(1,10),randint(1,10),randint(1,10))
...)
...
>>>

This approach will generally be slower though, since it has separate calls to the add() method for each
iteration.Usethe
timeit moduletoprovethattoyourself.

Now,let'squeryourrelation"R".Assumethatithastheattributecolumns(A,B,C).

>>>#SELECTA,BFROMRWHEREA=1
>>>fortinset((A,B)for(A,B,C)inRifC==1):printt,
...
(5,4)(10,4)(4,5)(6,1)(3,1)(9,10)(1,5)(8,8) (2,2) (3,7) (1,1)
(6,5)

Notice howPython used the names A, B, and C in thestatementto extract themembersofthetuples.


Thisisaverypythonicwaytoprocesstuplesandlistsandothercollections.

FormoreexamplesofSQLlikerelations,seethesectiononnamedtuples,below.

4.3.5SetMethods

Likeother builtinobjectsinPython,setshaveanassortmentofmethodsforprocessing,inadditiontothose
thathavebeendiscussed already.Fortheexamples,weassumethatthetwosets,RandS aredefinedas
follows:

>>>R=set([1,2,3])

>>>S=set([4,5,6])

Method Purpose Example


other
ReturnsTrueifthesetand have >>>R.isdisjoint(S)
other
isdisjoint( )
noelementsincommon. True
>>>R.union(S,[7,8,9])
Returnsanewsetfromtheunionofthe
other
union( ,...) set([1,2,3,4,5,6,7,
others
setandall .
8,9])
other
intersection( , Returnsanewsetfromtheintersection >>>R.intersection(S)
...) others
ofthesetandall . set([])
Returnsanewsetfromthedifferenceof >>>R.difference(S)
other
difference( ,...)
others
thesetandall . set([1,2,3])
>>>
symmetric_difference(
ot Returnsanewsetfromthesymmetric
R.symmetric_difference(S)
her
,...) others
differenceofthesetandall .
set([1,2,3,4,5,6])
>>>R.add(0)
elem
add( ) elem
Addselement totheset. >>>R
set([0,1,2,3])
>>>R.update([1,2])
Updatestheset,addingelementsfrom
other,...
update( ) >>>R
others.
set([0,1,2,3,1,2])
>>>R.remove(3)
Removesanelement elem fromtheset.
remove(
elem) >>>R
elem
RaisesKeyErrorif isnotinset.
set([0,1,2,1,2])
>>>R.discard(3)
elem
Discardstheelement fromtheset
discard(
elem) >>>R
ifitispresent.
set([0,1,2,1,2])
Returnsandremoveanarbitrary >>>R.pop()
pop()
elementfromtheset. 0
>>>R.clear()
Removesalloftheelementsfromthe >>>R
clear()
set. set([])
>>>
>>>len(S)
len() Returnsthesetcardinality.
3

4.3.6ImmutableSets

The standardset()objecthasan immutablecousin:frozenset().Afrozensetis asetthatyoucannotmodify


once itis built. Therefore, ithas none of the methods describedabovethatcanbeusedtoadd, removeor
update items in the set. You can build a frozen set from another set or other iterable (including a
comprehension):

>>>fromrandomimportrandint
>>>R=frozenset(
...(randint(1,10),randint(1,10),randint(1,10))
...for_inrange(100)
...)

However,youcannotbuildafrozensetusingthealternate,forloopmethod:

>>>R=frozenset()
>>>for_inrange(100):
...R.add(
...(randint(1,10),randint(1,10),randint(1,10))
...)
...
Traceback(mostrecentcalllast):
File"<stdin>",line2,in<module>
AttributeError:'frozenset'objecthasnoattribute'add'

Frozen sets are useful for testing fixed memberships. For example, suppose you had a list of all the
battleships thatwere sunkin WWII.If,atthestart ofyourprogram,youputthese into afrozenset,thenyou
cantestanyshipnametoseethatwasamongthosethathadsunk:

>>>sunken_battleships=frozenset(...)
>>>ifshipnameinsunken_battleships:
>>> print "The battleship {0} was sunk during World War
II".format(shipname)

4.4Dictionaries

4.4.1Buildingdictionaries

Dictionariesareasimple wayto mapuniquekeys todata.Forexample,supposeyouwantto keeptrackof


phone numbers. You could use a Pythondictionary, keyedby friends'names,where the data portion is a
phonenumber:

>>>number=dict(Bob="2125551212",Ted="2145551212",Carol="4165551212",
Alice="5145551212")
>>>number["Bob"]
'2125551212'

Here, we built a simple dictionary and added four telephone numbers to it. (Your friends may be good
sources of information!). We thenretrieved Bob's telephone number using thestandard look up. Python
alsoprovidesasimplifiedsyntaxfordefiningdictionarieswithstaticvalues:

>>>d={Bob:"2125551212",Ted:"2145551212",Carol:"4165551212",Alice:"5145551212"}

This produces the samedictionary asinthefirstexample.Betweenthebraces({...})youcanusekeywords,


asabove,ortwomemberlistsortuples.Seetheofficialdocumentationforafulldescription.

4.4.2Buildingdictionarieswithlistcomprehensions

Here'sanotherdictionarycontainingthefirst100squaresandthatwasbuiltusingacomprehension:

>>>one100squares={k:k**2forkinrange(100)}
>>>one100squares.get(99)
9801
>>>one100squares[100]
Traceback(mostrecentcalllast):
File"<stdin>",line1,in<module>
KeyError:100
>>>one100squares.get(100)
>>>one100squares.get(100,"Keynotindictionary")
'Keynotindictionary'

Inthis example,thedictionary isbuiltfromthesuccessive items that aregeneratesbythe comprehension.


The firstis[1,1]thesecond[2,4] andsoonupto[99,9801]. Noticehowtheget()methodoperates.Ifwe
ask for a key that is not there, we get nothing (and no exception is raised). However, we can supply a
secondargumenttotheget() function,whichis a default value that isto bereturned ifthekeyis notinthe
dictionary.

4.4.2ModifyingDictionaryEntries

Wecaneasilymodifyorremoveentriesinadictionary:

>>>one100squares[100]=100**2#Setuptheentryforonehundredsquared
>>>one100squares[100]
10000
>>>one100squares[100]=100**2.1#Changetheentrytoanillogicalvalue
>>>one100squares[100]
15848.931924611141
>>>one100squares.setdefault(100,100**3)#Trytosetanentryto100cubed
15848.931924611141
>>>one100squares.setdefault(101,101**2)#Trytoset101cubed
10201
>>>

>>>delone100squares[100]#Removeentrywiththekeyequalto100
>>>one100squares[100]
Traceback(mostrecentcalllast):
File"<stdin>",line1,in<module>
KeyError:100
>>>

Notice that the


setdefault() method does not modify the data associated with a key already in the
dictionary. However, if there is no such key, it adds the key with the data portion set to the second
argument.Also, setdefault() returnsthecurrentvalueatthatkeyafteritisdone.

For bulk updates to dictionaries,there isan


update()method thattakesanotherdictionary orlistor tuple
of key/value pairs as an argument and updates the dictionary with those new or changed values. For
example:

>>>d=dict((k,k**2)forkinrange(5))
>>>d
{0:0,1:1,2:4,3:9,4:16}
>>>d.update((k,k**3)forkinrange(3,7))
>>>d
{0:0,1:1,2:4,3:27,4:64,5:125,6:216}
>>>

4.4.3DictionariesasKeyedRelations

Dictionary keys and elements do not have to be simple strings and numbers. They can bemany things
(evenotherdictionaries).YoucoulduseadictionarytoemulateakeyedtableinanRDBMS:

>>>fromrandomimportrandint
>>>R=set(
...(randint(1,10),randint(1,10),randint(1,10))
...for_inrange(100)
...)
>>>
>>>keyed_R=dict(
...(A,(A,B,C))
...forA,B,CinR
...ifC==1
...)
>>>keyed_R[10]
(10,4,1)

Here,we'veemulatedatablewiththeattributes(A,B,C)usingAastheprimarykey.

4.4.4IteratingOveraDictionary

Python provides four waysto iterate overdictionaries. Youcandothatbykeyvalues,bydatavaluesorby


bothatthesametime.Herearesomeexamples:

>>>d=dict((k,k**2)forkinrange(3))
>>>d
{0:0,1:1,2:4}
>>>forkind:#Iterateoverthekeys(thedefault)
...printk
...
0
1
2
>>>forkind.iterkeys():#Iterateoverthekeys(explicitly)
...printk
...
0
1
2
>>>forvind.itervalues():#Iterateoverthevalues
...printv
...
0
1
4
>>>foriind.iteritems():#Iterateoverthekey/valuepairsastuples
...printi
...
(0,0)
(1,1)
(2,4)
>>>
>>>fork,vind.iteritems():#Iterateoverkey,valuepairs
...printk,v
...
00
11
24
>>>

The lastexampleshowsthat,whentheitemsreturned byaniteratoraretuples(or lists),youcan"takethem


apart"butspecifyingmultipleloopvariables,separatedbycommas.

There is also a method that allows you to extract key/value pairs from adictionary until itis empty. This
methodiscalledpopitem().Hereitisinaction:

>>>whilelen(d):
...printd.popitem()
...
(0,0)
(1,1)
(2,4)
>>>

4.4.5DictionaryMethods

Thefollowingtableliststheoperatorsandmethodsthatcanbeusedondictionaries:

OperatororMethod Purpose Example


key
Returns True if is [not] in the >>>1in{1:1}
key
[not]ind
dictionary. True
Returns the numberof items inthe >>>len({1:1})
len(d)
dictionary. 1
Returns the value of item having >>>{1:2}[1]
key
d[ ]
key
asthekey. 2
Creates or updates the itemhaving >>>d={1:2}
key
d[ ]=
value
key
asthekeytothevalue value
. >>>d[1]=3
Removes the item with the key
key
deld[ ] >>>deld[1]
key
fromdictionary.
Removes all items from the
clear() >>>d.clear()
dictionary.
copy() >>>d.copy()
Returnsacopyofthedictionary.
dict(d) >>>dict(d)
Creates a new dictionary with the >>>dict().fromkeys(['a','b'],0
seq[,value]
fromkeys( ) keysfromseqand the valuesset to )
value
. {'a':0,'b':0}
key
Returns the item with key from
key[,default]
get( ) the dictionary, orthedefault valueif >>>d.get('a',"NotFound")
keynotfound.
Returns a list of the >>>{1:1,2:2}.items()
items()

dictionary's(key,value)pairs. [(1,3),(2,4)]
Returns a list of the >>>{1:1,2:2}.keys()
keys()

dictionary'skeys. [1,2]
Returns a list of the >>>{1:3,2:4}.values()
values()

dictionary'svalues. [3,4]

Returns an iterator over a >>>fork,vind.iteritems():


iteritems()
dictionary'sitems. ...
Returns an iterator over a >>>forkind.iterkeys():
iterkeys()
dictionary'skeys. ...
Returns an iterator over a
itervalues() >>>forvind.itervalues():
dictionary'svalues
Removes the item with the key
key[,default]
pop( ) keyfrom dictionary and return its >>>d.pop('a',"Notfound")
default
valueor ifnotfound.
Removes and returns an arbitrary >>>{1:3,2:4}.popitem()
popitem()
(key,value)pairfromthedictionary. (1,3)
key
If is in the dictionary, return its >>>{1:3,2:4}.setdefault(1,4)
value.Otherwise, insertanewitem 3
key[,default])
setdefault(
with the key key
and value >>>{1:3,2:4}.setdefault(3,5)
default andreturn default. 5
>>>d={1:2,3:4}
>>>d.update(a=5)
Update the dictionary from >>>d
update(
other) other
iterable or keyword {'a':5,1:2,3:4}
arguments >>>d.update({6:7})
>>>d
{'a':5,1:2,3:4,6:7}

4.4.6UsingDictionariestoCategorizeandCount

One useful application for dictionaries is categorizing and counting. Suppose your programreads movie
data,where each movie is representedbyalist, and where the first elementis the movietitle,thesecond
element isthedirector ofthemovieand the otherelementsincludeotherdata. Supposeyouwanttocount
the number of movies produced by each directory. Using standard dictionary methods, you might do
somethinglikethis:

>>>directors={}
>>>formovieinget_movies():
...ifmovie[1]indirectors:
...directors[movie[1]]+=1
...else:
...directors[movie[1]]=1

Alternatively,youcouldusetheget()methoddescribedabovetosimplifyyourprogram:

>>>directors={}
>>>formovieinget_movies():
...directors[movie[1]]=directors.get(movie[1],0)+1

4.4.7Usingdefaultdict

Thereis,however,aspecial kind ofdictionaryavailableinthecollectionsmodule called defaultdict:Hereis


howwecanuseittosolvethesameproblem:

>>>fromcollectionsimportdefaultdict
>>>directors=defaultdict(int)
>>>formovieinget_movies():
...directors[movie[1]]+=1

Adefaultdictsetsa default data typetobe used to automatically create entries for keys thatarenotinthe
dictionary. Inthisexample,weusedthe datatype int whichmeansthatfor everynewkey,anentrywillbe
added to the dictionary with the key
movies[1] and the value i nt(),which defaultsto 0. Note that the
argumentsupplied to defaultdict must be
callable that is itmustbesomesortoffunction ormethod.
Thatis why you cannot just code
defaultdict(0) , even thoughatfirstglance,thatmightseemtomake
sense. Intheexamplebelow, thefirst time Stephen Spielberg isencountered,an entry will beaddedwith
his name as the key and a data value of 0. However, this happens inside an augmented assignment
statement.Thus,theverynextthingthathappensisthat1isaddedtothe entry.0+1=1 sotheentrynow
hasStephenSpielbergasthekeyand1asthevalue,asshownbelow:

>>>fromcollectionsimportdefaultdict
>>>directors=defaultdict(int)
>>>directors["StephenSpielberg"]+=1
>>>fork,vindirectors.iteritems():
...printk,v
...
StephenSpielberg1

Suppose that, instead of counting movies, you want to make a list of the movie data by director.
defaultdict canhandlethistaskaswell:

>>>fromcollectionsimportdefaultdict
>>>movies_by_director=defaultdict(list)
>>>formovieinget_movies():
...movies_by_director[movie[1]]+=[
...movie[0:0]+movie[2:]
...]

The entries of the movies_by_director dictionarywillconsist of alistofmoviedata. Everyiteminthe listwill


itselfbe a listofdataextractedfromtheitemsreturnedbythefunctionget_movies(), excludingthe director's
name(whichbecomesthekey).

4.5NamedTuples

Sometimes,thelistsandtupleshaveastructurethatis not visibleat first.Forexample,ifwereaddatafrom


a databaseusingan SQL query, we will receivea list ofitemsfor each rowofthequery.However,thelist

contains the attributesspecified in the SQL querycommandandintheorderspecified.Thatmeansthat ifI


sendthiscommandtoanRDBMS:

SELECTA,B,CFROMR

We will getback rows withtheattributes in thatorder.However, thisdata isreturnedtoaPythonprogram


asasimple list. Ifwe haveaPython variablecalledrow, for example, wehave torememberthatrow[0]is
"A", row[1]is "B"androw[2]is"C".Notonly isthistedious,itiserrorprone,sinceImightinadvertentlycode
the wrong item number. Worse, what if the SELECT statement is modified at some point to return the
attributes in a different order? Named tuples give us a method to avoid these problem and make our
programsmorereadableandmaintainableaswell.Let'slookatanexampleofhowwemightdothat:

>>>fromcollectionsimportnamedtuple#Getthenamedtupletype
>>>R=namedtuple("R","A,B,C")#Defineanamedtupleforourrelation
>>>conn=connect("database")#Connecttoourdatabase
>>>cursor=conn.cursor()#Getacursor
>>>cursor.execute("SELECTA,B,CfromR")#ExecuteanSQLSELECT
>>>forrowinmap(R._make,cursor.fetchall()):
#Iterateovertherowsthatwegotback
...printR.A,R.B,R.C
#Printtheattributesfromeachrow

Taking this apart, we firstimportthemoduleweneed,thenusethenamedtuplefunctiontosetupnamesfor


ourrelation"R".Inthenextthreelines,weconnecttothedatabase.(We'll coverdatabaseaccessmethods
in a laterchapter).Our for loopuses the named tuple. Let'slook at itmore closely.Firstof all,itusesthe
map function, whichtakesatleast two operands. The first is afunctiontobeperformed R._makeinthis
case the second is an iteratorthatreturns 0 ormore items
cursor.fetchall()inthis case. Then,
map calls the functionfor everyitem returnedby theiteratorandreturnstheresulttothecaller,theforloop
inthiscase.

What does the function


R._make do? This function was createdin the second statement of the example
that called
namedtuple . The
_make
functionthen takes whateverit gets andreturns a structuresothat
youcanrefertotheitemsbyname.Hereisanotherexamplewithsomerealdata:

>>>movies=[
...["StarWars","GeorgeLucas"],
...["TheMatrix","AndyandLanaWachowski"],
...["CloseEncounters","StephenSpielberg"],
...]
>>>movie=namedtuple("Movies","title,director")
>>>formovinmap(movie._make,movies):
...print"{0:<20}{1:<20}".format(mov.title,mov.director)
...
StarWarsGeorgeLucas
TheMatrixAndyandLanaWachowski
CloseEncountersStephenSpielberg

If,atsomefuturepoint, the dataispresentedinadifferentorder,theonlythingwehavetochangeisthecall


tonamedtuple .Therestofourprogramcancontinueasunchanged.

4.6DoubleendedQueues

Acommon programmingproblemistomanagelistsof thingstodo orthingsto workon.Sometimesyouwill


want to put things on the end of the list andtake them offthestart (FIFO, or first in,firstout)othertimes
youwill needtoputthemon thestart andtakethemfromthestart(LIFO,orlastin,firstout).Youwouldbe
able to dothis using regularPython lists and the append()and pop()methods,buttheseoperationsare
so common that there is a special, highperformance data type customized for just this sort of use.Itis
called a
deque , which is pronounced like "deck" andstands for "doubleended queue".This data type is
foundinthecollectionsmodule,where namedtuple isalsofound.Hereisasimpleexample:

>>>fromcollectionsimportdeque#Importthedequedatatype
>>>lifo=deque()#Makeanewdeque
>>>foriinrange(5):#Add5newitems
...lifo.append(i)
...
>>>whilelifo:#Takeoffallitems,LIFO
...printlifo.pop()
...
4
3
2
1
0

Ofcourseyoucanputanythingyoulikeintoa deque:integers,strings,lists,tuples,dictionaries,functions
evenotherdeques!Here'showyoucoulduseadequeforaFIFOqueue:

>>>fifo=deque(iforiinrange(5))#MakeaFIFOdeque
>>>whilefifo:
...print(fifo.popleft())#Takeoffallitems,FIFO
...
0
1
2
3
4

Here,we showthat using the popleft()method removesitems from the left of the queue. Wecanalso
seethata
deque cantakeacomprehension(orotheriterable)asanargument.

The followingtable lists themethods that can be usedwithdeques. Assumethat we have a dequecalled

"deck".

Method Purpose Example


iterable
Make a new deque from ,
iterable,maxlen
deque( ) limiting its length to maxlen deck=deque(maxlen=10)
(defaultisnolimit).
Add an item totherightsideofthe
item
append( ) deck.append(1)
deque.
Add an item to the left side of the deck.appendleft("Deques
item
appendleft( )
deque. arefun!")
Removes all of theitemsfromthe
clear() deck.clear()
deque.
Adds all the itemsfrom
iterable to
iterable
extend( ) deck.append([1,2,3])
therightsideofthedeque.
Add all the items from
iterable to deck.extendleft(range(10,
iterable
extendleft( )
theleftsideofthedeque. 5,1))
Returns the numberof items inthe
deque
len( ) len(deck)
deque.
Remove and return the item from
pop() deck.pop()
therightsideofdeque.
Remove and return the item from
popleft() deck.popleft()
theleftsideofdeque.
Remove the first item found (from
value
remove( ) deck.remove(1)
value
left)thatisequalto .
Rotate the deque n items to the
n
rotate() right. If
n is negative, rotate left deck.rotate(1)
instead.

4.7Exercises

1.UsingaDictionarytoCollectObjects

Write a function that examines Python's search path and builds and returnsa dictionarythat collectsthe
pathsby the prefix consisting ofthefirsttwodirectoriesinthepath.Allofthedirectoriesbelowthat,willbein
alistthatisthedataportionofthedictionaryentry.Forexample,ifthesearchpathhadtheseentries:

/foo/bar/fum
/foo/bar/foe
/fum/foo/bar

Yourdictionarywouldlooklike:

{"/foo/bar":["fum","foe"],"/fum/foo":["bar"]}

Be sure to allow for empty strings in the path and for path prefixes with no subdirectories.To test your
function, write a second function that takes the dictionary you build and prints it by each entry in the
dictionary,indentingthesubdirectoriesfourspaces.Withtheaboveexample,youroutputshouldlooklike:

/foo/bar
fum
foe
/fum/foo
bar

2.Usingadictionarylikeakeyedtableinarelationaldatabase

Assumethatyouhavethefollowingdictionarystructureforthemoviedata:

{"titleyear":("director",("star1","star2",...)),...}

Oneentrymightbe:

{"StarWars1977":("GeorgeLucas",("CarrieFisher","MarkHamill","Harrison
Ford"))}

(a)Write a functionthatbuildsthedictionary by promptingtheuser for input foreachpieceofdata.(You'll


need a way to indicate that you have entered the last star name.) Populate the dictionary using your
functionanddatafrommoviesthatyoulike.

(b) Write a function that accepts the dictionary you built in part (a) and a second argument with the last
name of a star. Print all movies where that star appears in your dictionary. Format the print using
indentationandlabelsforthetitle,year,directorandcast.

3.Usingalistlikeamatrix

A Python list can have lists as entries. That means that it is not difficult to define arrays, since a
twodimensionalarray isno more than a tablewithrows (theouter list) andcolumnsineachrow(theinner
list).

(a)Write a functionthatbuildsanarrayusingsuchatwodimensionallist.Thefunctionshouldtakeasinput
the number of rows and columns for the array and populate the array with random integers in a range
specifiedasthethirdandfourthargumentsofthefunction.Atypicalfunctioncallwouldlooklike:

myarray=build_array(10,10,1,100)

(b) Write a second function that performs matrix multiplication. This function will take in two arrays and
returnthe resultofthecomputation. It must check thatthematrices arefullycompatibleforthe operation.
Usingtheresultfrompart (a), test thisfunction and checkyourresults byhandorbyanyothermeansthat
youlike.

Chapter5Modules
5
5.1TheBigPicture

Whenyour programgets bigger and you write more code,youwillgettired of usingtheinterpreter.Thisis


because the code that you created in the interpreter is only valid in that session. Once you quit the
interpreter you can never use that code again. Wouldn't it be nice if you can reuse code you wrote in
differentsessions?

Withmodulesyoucan!

Besidesthat,modulesareusedto:

Separatecodewithdifferentconcerns
Organizecode
Reusecodemadebysomeoneelse

5.2Introduction

WhenyouquitthePython interpreter, allthefunctiondefinitionsandvariablesyouhavecreatedarelost,as


youcanseeintheexamplebelow:

>>>message="hello,world"
>>>defhelloworld():
...printmessage
...
>>>helloworld()
hello,world
>>>
>>>quit()
$python
Python2.6.4rc2(r264rc2:75497,Oct202009,02:55:11)
[GCC4.4.1]onlinux2
Type"help","copyright","credits"or"license"formoreinformation.
>>>helloworld()
Traceback(mostrecentcalllast):
File"<stdin>",line1,in<module>
NameError:name'helloworld'isnotdefined

>>>

To beable to tousethem,youwouldhavetorewritethosefunctiondefinitionsandvariablesagain.To save


yourself some time, you can write your function definitions and variables in a file. By doing this you can
reusetheminthedifferentprogramsyouwrite.

5.3Defintion
InPython,
modules
arefilesthatcontainfunctiondefinitions,variablesandstatements.

You can use your favorite text editor to write your modules. These files are saved with a .py extension.
Therearetwowaystousepythonmodules:eitherimportthemorexecutethemasascript.

5.4ImportingModules

Copythefollowingcodeintoatexteditorandsaveasfunctions.py:

>>>deffactorial(num):
...factorial=1
...whilenum>0:
...factorial*=num
...num=1
...returnfactorial
>>>defsquare_sequence(n):
...result=[]
...fornuminrange(1,n+1):
...result.append(num*num)
...returnresult
...

Youcannowmakeuseofthisfunctionevenafteryouquitthepythoninterpreterbutfirst,

you have to make sure thatintheterminal you arein the current directory whereyousaved your
module
youhavetoimportthemoduleintothecurrentsession

Okay,letususethemodulewejustsavedinaninteractivesession:

>>>importfunctions

>>>functions.factorial(3)

Youmayassigntheimportedfunctiontoalocalvariableifyouthink"functions.factorial(...)"istoolong:

>>>fact=functions.factorial
>>>fact(3)

ButwhatifIneedonlythesquare_sequencefunctioninthesessionandnotthefactorialfunction?

Avariationoftheimportstatementallowsyouonlytoimportthesquare_sequencefunction:

>>>fromfunctionsimportsquare_sequence
>>>square_sequence(3)
[1,4,9]

Youcanalsoimportallofthefunctions,denotedbyanasterisk,thiswayifyou'refeelinglazy:

>>>fromfunctionsimport*
>>>factorial(3)
>>>square_sequence(3)
[1,4,9]
>>>

Notehoweverthatthispracticeisfrowneduponbecauseitmakesthecodelessreadable.

Other modulescan also import modules. Thisis done,forexample,whenamoduleneedsafunctionthat is


withanothermodule.

Toillustrate,considertheformulagiveninChapter2,

Thefollowingisafunctionthatapproximatesthesineofx:

frommathimportfactorial,pi

defsin(x,t=10):
sign_of_x=1.0ifx>=0else1.0
x=float(abs(x))%(2.0*pi)
s=0.0
foriinrange(1,2*t,2):
sign=1.0if(i1)%4else1.0
s+=sign*x**i/factorial(i)
returnsign_of_x*s

Copyandpastethecodeaboveintoatexteditorandsaveitastrig.py.

Then,importyourmoduleandtestit:

>>>fromtrigimportsin
>>>sin(1)
0.8414709848078965

Notice that the function has a second argument,t whichcontrols the number of termsintheexpansion of
the series. Experiment with different valuesoft andseewhat size of twillcausethefunction to returnthe
samevalues as the functionof thesame nameinthemathlibrary. Also,seeifyoucanrewritethis function
intoaonelinelambdausingacomprehension.

5.5ExecutingModulesasscripts

Earlier,wesaidthatmodulescanberunasascript.Thismeansthatwecancallthefunctionsin(x)inthe
moduleitselfwithagivenparameter.Wecandoawaywiththeimportingitintheinterpreterandenteringthe
parametersourselves.Infact,wearegoingtotakeitastepfurther,wearegoingtomakeourtrigmodule
askinputfromtheuser!

Todothis,weaddthefollowingcodeattheendofourfiletrig.py,

if__name__=="__main__":
x=input('x?')#asksuserforaninputthatgetsassignedtox
print"sin("+str(x)+")="+str(sin(x))

The conditional statement


ifname==__main__: lets our trig.py act as a standalone program. When
you'reusingtheinterpreterthinkofitasthe__main__atthatmoment.

Think of
__main__ as containing the code that we currently want to execute. The interpreter executes
everythingcontainedin__main__.

Toexecutetrig.pyasamodulewefeeditasaparameterwhenwefireuptheinterpreter,

oem@orange~/Desktop/SampleCode$pythontrig.py
x?2
sin(2)=0.909297426826

Makesuretochangetothedirectorywheretrig.pyisbeforerunningthiscommand.

The difference is that in the case above, the trig.py module's name becomes __main__ and not trig,
however,whenweimportitintheinterpretertousesin,asyoucanseebelow:

>>>importtrig

>>>trig.sin(2)
0.90929742682568171
>>>trig.__name__
'trig'
>>>
Infact,the__main__atthatmomentistheinteractiveinterpreter,
>>>__name__
'__main__'

5.6Thedir()function

The dir() function returns alistof stringsthat listsdownallthenamesinamodulefromvariables,functions


andevenimportedmodules.

Considerourtrigmodule,

>>>importtrig
>>>dir(trig)
['__builtins__','__doc__','__file__','__name__','__package__','factorial',
'sin']

Expect each stringto return something when you call them. We've alreadydiscussedthesin and factorial
methodsaswellasthe __name__ attribute.

The
__doc__
attributereturnsnothingbecausewedidn'tcodeinadocstringinthetrigmodule:

>>>trig.__doc__

The
__file__
attributereturnsthenameofthecompiledversionofthemodule:

>>>trig.__file__
'trig.pyc'

Without an argument, the


dir() function returns a list of names variables,functionsand modules
thatyouhavedefined:

>>>numbers=range(1,5)
>>>importtrig
>>>sin_func=trig.sin
>>>sin_func(1)
0.8414709848078965
>>>dir()
['__builtins__','__doc__','__name__','__package__','numbers','sin_func',
'trig']

As you can see,thenameswe createdare there:


numbers,sin_funcand trig. You caninferbynow
that the names __builtins__,__doc__,__name__ and __package__ are names included by
default.RefertotheofficialPythondocumentationformoreinformationaboutthem.

5.7Packages

Packages
provideawaytoorganizeyourmodules.

It's similarto thewaythat we organizeoursongs into genresinourphonesoronour filesystem.There'sa


folderorplaylistforsay,rockmusicandanotheroneforclassicalandanotheroneforalternative.

Creating packagesare notallthat hard.Packages arejust different folders containingmodulesonyourfile


system.Forexample,

chapter
__init__.py
trig/
__init__.py
sin.py
cos.py
factorial_script.py
others/
__init__.py
fact.py
square_sequence.py

The
__init__.py inside each foldermakes Pythonrecognize the folderas a Python package.If afolder
doesn'thavean
__init__.py ,thenPythonsimplyseesitasafolder.

5.7.1Importingmodulesfrompackages

Let's say Iwant to writeaseparate module thattakesan input x andgets the factorialofx.We've already
written the factorialfunction in
fact.pybeforeandso we canreuse that!We can import modules inthe
interpreterorfromanothermodule,

Todosousingamodule,

fromchapter5.others.factimportfactorial

if__name__=='__main__':
x=input('x?')

printfactorial(x)
#youcanalsodoitthisway:importchapter5.others.factbutyouwouldhave
toqualify
#thefunctionaschapter5.others.fact.factorial(x)butthat'swaytoolong
and
#youwouldn'twantthatwouldyou?

Makesurethatthefactorial_script.pyisinsamefolderwhereyourchapter5folderisplaced:

SampleCode/
chapter5/
__init__.py
...
...
others/
factorial_script.py

Runningthescript,

oem@orange~/Desktop/SampleCode$pythonfactorial_script.py
x?3
6

Usingtheinterpreter,

>>>fromchapter5.others.factimportfactorial
>>>factorial(3)
6

orsimilarly,

>>>importchapter5.others.fact
>>>chapter5.others.fact.factorial(3)
6

5.7.2Modulesreferencingfromothermodules

There is a problem with our existing


trig.py
code,whereit attempts to refertofilesinthe samefolder
thatarenolongerthere:

fromfunctionsimportfactorial
defsin(x):
sequence=[1]
foriinrange(2,20):
ifi%2:
sequence.append((1.0ifsequence[1]>0else1.0)
*x**i

/fact(i))
returnsum(sequence)

if__name__=="__main__":
x=input('x?')
print"sin("+str(x)+")="+str(sin(x))
sin.py

Insection5.4oursin.pyandfact.pywereinthesamefolder,

chapter5/
sin.py
functions.py

That is why there is noproblemwith using the directive


fromfunctionimportfactorial . Butwe
have reorganizedourcodeintopackages sincethen.We placed our sin
moduleinthe
chapter5.trig
package and the factorial function from functions.py to fact.py in the
chapter5.others
package.

Thus, our current code won't work because it is trying to import the factorial function from the functions
modulebutitisnotthere.

oem@orange~/Desktop/SampleCode$python
Python2.6.4rc2(r264rc2:75497,Oct202009,02:55:11)
[GCC4.4.1]onlinux2
Type"help","copyright","credits"or"license"formoreinformation.
>>>fromchapter5.trig.sinimportsin
Traceback(mostrecentcalllast):
File"<stdin>",line1,in<module>
File"chapter5/trig/sin.py",line1,in<module>
fromfunctionsimportfactorial
ImportError:Nomodulenamedfunctions
>>>

Tomakeitwork,weneedtoimportthefactorialfunctionfromchapter5.others.fact:

Thismeans
thatinsteadofstartingwith:

fromfunctionsimportfactorial

Wechangethefirstlinetowhatyouseebelow:

fromchapter5.others.factimportfactorial
defsin(x):
sin_x=0
forninrange(1,20):
...
...

Now,ourprogramworksagain!

>>>fromchapter5.trig.sinimportsin
>>>sin(1)
0.8414709848078965
>>>

5.8Howdoestheinterpretergoaboutlookingforyourfiles?

Whether you arecoding from the interpreter or using modules,whenever you import a module,thePython
interpreter first looks inthecurrent directory for thatmodule. If themoduleisnot present, thenitgoesonto
lookateachdirectoryinthelist sys.path .

Toseethelistofdirectoriesinthe
sys.path
:

>>>importsys
>>>sys.path
['','/usr/lib/python2.6','/usr/lib/python2.6/platlinux2',
'/usr/lib/python2.6/libtk','/usr/lib/python2.6/libold',
'/usr/lib/python2.6/libdynload','/usr/lib/python2.6/distpackages',
'/usr/lib/python2.6/distpackages/PIL',
'/usr/lib/python2.6/distpackages/gst0.10','/usr/lib/pymodules/python2.6',

'/usr/lib/python2.6/distpackages/gtk2.0',
'/usr/lib/pymodules/python2.6/gtk2.0',
'/usr/local/lib/python2.6/distpackages']
>>>

Chapter6ObjectOrientedProgramming
6
6.1TheBigPicture

Intheearlier chapters, weprogrammedby makingafunctionandtheninvokingit.Sometimeswewouldjust


write the codestep by step withoutmakingafunction. Thisformofprogrammingisknownasimperativeor
procedural. Imperative programming is goodforsmall programs but asyour program becomes larger and
the specifications become morecomplex,a new approachisrequired.Thus,researchersdevelopedObject
OrientedProgramming(OOP)toaddressthatproblem.

Object Oriented Programming is a


programming style where an ecosystem of objects cooperate to
performatask.

6.2ObjectOrientedProgrammingversusProceduralProgramming

Thinkofprocedural programmingas one personthat doesatask. If thetask becomes morecomplex,it is


harder for just one person to execute that task. Adding someone to help him, the task becomes half as
complex. If hecanenlistmorehelpthen hecanbreakdown the taskintosubtasksanddelegatethem.This
istheideabehindobjectorientedprogramming.

Look at the thingsaround you.Youareprobablysitting onachairrightnow orlyingdowninbed.Thechair


andthebedareobjects.This bookyou'rereadingis alsoanobject!Lookoutside.Theremaybecarsdriving
byor a dog running around.Thesetooareobjects.Thingsweseeinthereal lifeareobjects.Youcanalso
beconsideredasanobject!

What other reallife entities can you think of? These can probably all be represented in the computer as
objects.

Anobject is usuallyareallife entitythattheyou,theprogrammer,triestorepresentonthecomputer.Ithas


attributesandbehaviours.

Nowthatwehaveidentifiedanddefinedwhatobjectsare,letustalkaboutattributes.

For example, a car's attributesareitsmake,model,color,seatingcapacity.Dogs belong toacertainbreed.


Theycomeindifferentcolors, Some have fur, anssomehaveno fur at all. As a student youhaveaname
andstudentnumberandalistofsubjectsthatyouaretaking.

Attributes define an object. These are what make an object unique. They usually come in a setwhich is
unique tothat object.For example, a dog's attributes can beitsbreedandname.Althougha studenthasa
nameaswell,itdoesn'thaveabreed.

Attributes
areanobject'scharacteristics.

Aside from attributesan object alsohas behaviours .Dogs cansitstand,rollover,bite


, andfetch
afrisbee.
sleep
You, as a person, exhibit a variety of behaviours. You go to eat
, study
, play
, ,etc. Right now you
read
are ingthisbook.Youmighthavesomesortofbeveragenexttoyouthatyoucan drink.

Thereareso many behavioursthat an objectcanperform! Inthenext sectionwewillmaketheconnection


betweenreallifeobjectsandobjectsinprograms.

areactionsthatanobjectcanperform
Behaviours .

6.3Classes

Before wecancomeup with objects in aprogram,we must specifyhowanobjectmustlooklike.Thiscan


bedonebycomingupwithaclass.

A
class
isablueprintofanobject.Itcontainsthetheattributesand/orbehavioursofanobject.

Aclassisnottheobjectitselfbutratherthedesignoftheobject.

Let'sstartmakingastudentobject!Tocodeaclassthemostbasicsyntaxforaclassdefinitionis:

classClassName:
defmethod_name(self,[optionalarguments]):
<statements>

Let'snameourstudentclassStudent:

>>>classStudent:
...pass

ThecodeabovefollowsthebasicsyntaxinFigure6.1forcreatingaclass.

The passstatementsays that,rightnow,theStudent classhasnothinginitnoattributesnorbehaviours.


We put thepassstatementbecausethesyntaxaboverequiresthatastatementshouldbepresent.Since,at
this point, we don't want to do anything, we put the pass statement which simply means that it will do
nothing.

6.3CreatinganObject

Nowwehaveastudentclass.Letusstartbycreatingstudents.

>>>classStudent:
...pass
...
>>>s1=Student()#Createss1asaninstanceofStudent
>>>s2=Student()#Createss2asaninstanceofStudent

Wenowhavetwostudents!Whatwejustdidwasto
instantiate
twoinstancesofclassStudent.

Instantiation
referstocreatinganewobjectthatfollowsthedesignandcharacteristicsofacertainclass.

Inthis case, weinstantiated two objectsof the Student class.student_oneandstudent_twoarebothcalled


instancesofclassStudent.

6.4Attributes

The twoinstances we created abovearenotvery useful.They do not yet havenamesorstudentnumbers


andwedon'tknowwhatsubjectsthey'retaking.

Tomakeitlookmorelikeastudentletusaddsomeattributes:

>>>classStudent:
...pass
...
>>>s3=Student()
>>>s3.name="Jose"
>>>s3.student_number=1234
>>>s3.subjects=["Math","English"]
>>>print"s3studentsname:",s3.name
s3studentsname:Jose
>>>print"s3studentnumber:",s3.student_number
s3studentnumber:1234
>>>print"s3student'ssubjects:",s3.subjects

student'ssubjects:['Math','English']

Initially, our Student class has no attributes. If we were to call s3.name before setting it, thenthat would
causeanAttributeError:

>>>s3.name
Traceback(mostrecentcalllast):
File"<stdin>",line1,in<module>
AttributeError:Studentinstancehasnoattribute'name'
>>>

Alternatively, you might wantto instantiateobjectswhose characteristics havealready been customized in


the class(
Student ). This can be donebydefiningaspecialmethodcalled __init__(self,...) ,andis
often what you see in structured languages like Java. The attributes of a class are set first they do not
change,onlytheirvaluescan.

Whenever a class is created, the


__init__(self,...) methodiscalledtosetanewlycreatedclassto
a specific state. The
__init__(self,...) method takes in a required parameter,
self and other
parametersthatareneededtosetthestateofanewinstanceoftheclass.Considerthecodebelow:

>>>classStudent:
...def__init__(self,name,student_number,subjects):
...self.name=name
...self.student_number=student_number
...self.subjects=subjects
...

The function __init__(self,...) which takes in the required parameter self. Think of
self as
referring to the new class being created atthat time.In fact,
self
isjusta convention. Youcanusethe
word me or
this,justlikeinJava,torefertothe instance.Notethatwhenwritingthe__init__()method,
"__
"is a double underscore.In theexampleabove, __init__isusedtosetaname,student_numberand
a list of subjects. This automatically gives instances of the class Student the attributes, name,
student_numberandsubjects,whosevaluescanbesetatthetimeofinstantiation.

For example, the code below creates a new instance of class Studentwithname Jose, studentnumber
1234,takingthesubjectsCalculus,andProgramming.

>>>s1=Student(name="Jose",student_number=1234,subjects=["Calculus",
"Programming"])

To makethingseasier,if you know the orderofarguments when creating aninstance,youdo not haveto
writeouteachoftheattributesnames:

>>>s2=Student("Dan",5678,["FineArts","Communication"])

Attributesareessentially public.There isno suchthing asa trulyprivateattributeinPython.However,if


youinsist, prefixanyattributewith a double underscore.(There isalways a wayto getat these in Python,
usingintrospection,althoughthatisoutsidethescopeofthisintroductorytext.)

>>>classStudent:
...def__init__(self,name):
...self.__name=name
...

Forexample,tryingtoaccesstheprivatevariable
__name
willresultinanerror:

>>>student_one=Student("Jose")
>>>student_one.__name
Traceback(mostrecentcalllast):
File"<stdin>",line1,in<module>
AttributeError:Studentinstancehasnoattribute'__name'

If you're coming from a staticallytyped background, you might be wondering why there are no private
variablesinPython.ThesimpleansweristhatthisisjustapartofthePython'sprogrammingphilosophy.

Whenan attributeisprefixedthisway(i.e.,withadoubleunderscore__),itdoesnotmeanthatyoucannot
access itatall. Itsimply means that the attribute ispart oftheimplementation detail of say for instance, a
method ora class. There are certainly ways tohack or tosnoop aroundtheprivacy ofa "private" variable
andto accessit.Butthismaymakethingstoocomplicated,so,intheend,itisoften bettertojustkeepallof
theattributes"public".

Justincase you need to know how to access"private"attributes in Python, you will needtoaddamethod
thatretrievesthename:

>>>classStudent:
...def__init__(self,name):
...self.__name=name
...defget_name(self):
...returnself.__name
...
>>>student_one=Student("Jose")
>>>printstudent_one.get_name()
'Jose'

>>>printstudent_one.name
'Jose'

Additionally,youcanincludeasettermethodifyouwanttoallowforthechangingof"private"attributes:

>>>classStudent:

...
...
...defset_name(self,name):
...self.__name=name

>>>student_one=Student("Jose")
>>>printstudent_one.get_name()
Jose
>>>student_one.set_name("Dan")
>>>printstudent_one.get_name()
Dan

Simulatingprivateattributeslikethisandaddingmethods toretrieveandsetthemissocommon thatPython


has a shortcut, the
property() function. Take a moment to look it upintheofficialdocumentationand
reworktheexampletouseit.

6.5Behaviours

Now that we have made our student objects look more studentlike, let's make them
behave more like
students.

We begin by writing functions to reflect Student behaviours. One common way is to assign
functionsdefinedoutsideoftheclassasalocalvariableofthatclass.

>>>defstudy():
...print"studying"
...
>>>a_student.study=study
>>>a_student.study()
studying

Functionscanalsobecodedwhenyoudefineaclass:

>>>classStudent:
...def__init__(self,name,sid,subjects):
...self.name=name
...self.sid=sid
...self.subjects=subjects
...defstudy(self):
...print"studyingnow"
...defask(self,question):
...printquestion
...deflisten(self):
...print"ZZZZZZZZ"

The followinglinesshow ourstudent instanceexecuting its studentmethods.Nowourstudentis actinglike


astudent!Outputisshownbelow.

>>>s1=Student("Jose",1234,["Calculus","Programming","Biology"])
>>>s1.listen()
ZZZZZZZ
>>>s1.ask("Whatisthesquarerootof4?")
Whatisthesquarerootof4?
>>>

6.6Inheritance

OneofthemainconceptsinObjectOrientedProgrammingis
inheritance
.

Inheritance
iswaytocreateanewclassfromanexistingclass.

6.6.1ExtendingCreatedClasses

ForexampleifwewanttocreateanewclasscalledCollegeStudent,wecouldcodeitfromscratchlikethis:

>>>classCollegeStudent:
...def__init__(self,name,sid,subjects):
...self.name=name
...self.sid=sid
...self.subjects=subjects
...defstudy(self):
...print"studyingnow"
...defask(self,question):
...printquestion
...deflisten(self):
...print"ZZZZZZZZ"

However,did you noticethat


CollegeStudentis almost the same as our
Student classinSection 6.5?
Insteadof defining a completely new classfor
CollegeStudent
,a muchbetter way maybetoreuseor
inheritthecodefromtheStudent class.

ThesyntaxforinheritanceinPythongoeslikethis:

classClassName(ParentClassName):
defmethod_name(self,[optionalarguments]):
<statements>

The parent class refers to the class whose code is to be inherited. In ourcase,the
CollegeStudent
class makes use of Student class to define itself. This makes Student the parent class as
CollegeStudent thesubclass.

Usually
subclasses are createdbecause weneedtoputinnewattributesorbehavioursthatmay ormay
not necessarily apply to the parent class. Think of the parent class as a more general type of a class.
Subclassesaremorespecific.

Goingbacktoourexample,

>>>classCollegeStudent(Student):
...def__init__(self,degree,major):
...self.degree=degree
...self.major=major
...

Thesubclass
CollegeStudent
inheritstheparentclass
Student
.Thismeansthat:

CollegeStudent has the attributes of


Student
name, student_number and
list_of_subjects
CollegeStudent exhibitsthebehavioursofStudent
study,ask,listen .
CollegeStudent is given additional attributes,
degree and
major
that the parent class,
Studentdoesnothave.

Likeaddingnewattributes specific to acollegestudent, wecanadd new


behaviours that arespecific to a
collegestudent:

>>>classCollegeStudent(Student):
...def__init__(self,degree,major):
...self.degree=degree
...self.major=major
...defcut(self,class):
...print"feelinglazy,won'tgoto%sclass"%class
...defstudy():
...print"sippingcoffeewhilegoingthroughatonofreadings"

As you can see in the example above, the


CollegeStudent was given the behaviours of
cut
and

study,thatarespecificto
CollegeStudent andnotfoundinitsparentclass,
Student
.

Finally, subclasses can change behaviours that are inherited. This is called overriding a function. For
instance we might want to change how the
study() function is to reflect how a college student really
studies.

>>>classCollegeStudent(Student):
...def__init__(self,degree,major):
...self.degree=degree
...self.major=major
...
...defcut(self,class):
...print"feelinglazy,won'tgoto%sclass"%class
...defstudy(self):
...print"studyingwhilesippingcoffee"

...
>>> college_student = CollegeStudent("Jose",1234,["Calculus","Computer
Programming",])
>>>college_student.study()
studyingwhilesippingcoffee
>>>

6.7Exercises

1.CreateaSectionclasswithasectionid,coursetitle,instructorandstudentsasclassvariables.

2.CreateanInstructorclassthathasanameandlistofsubjectsbeingtaughtasitsclassvariables.

3. All objects in Python inherit from the Object class. Override thatclass'
__contains__ method inthe
Sectionclasssuchthatwecandothis:

>>>section=Section(1,"Algebra",Instructor("Raul"),["Jose","Luis"])
>>>"Jose"insection
True
>>>

4.Modify the Section class to allowstudentstobe addedtoasection evenafterobjectcreation.Also allow


forcheckingofthecurrentsizeofthesection.Forexample,

>>>section=Section(1,"Algebra",instructor,["Jose","Luis"])
>>>section.add("Roberto")
>>>section.size()
3

5.Allowiteratingoverasection'sstudentssuchas:

>>>forstudentinsection:
...printstudent
Jose
Luis
Roberto

7
Chapter7DatabaseConnectivity
7.1TheBigPicture

The Python DB API provides a common interface to access relational databases like DB2. With this
specification, ourPython programs can accessdifferentdatabasesusingthesamesyntaxwithoutknowing
details of each specific database. It is up to the drivers of each database to handle these detailsfor us.
TherearealotofDB2driversforPython.InthisbookwewillusethedriverprovidedbyIBM.

ThefollowingfigureillustrateshowourPythonprogramsinteractwithrelationaldatabases.

OurPython codecontainsour SQL queries.TobeabletoaccessIBMsDB2,itaskshelp from IBMDBan


implementation ofthe Python DB API 2.0. IBM DB containsthecodethatwilltakeourqueriesand runiton
IBMDB2.Todothis,itusesthetheIBMDB2ODBCDriverthatiswrappedwithit.

7.2Prerequisites
BeforewecanuseDB2,thereareseveralthingsthatwehavetodo:
Get a copy of IBM DB2ExpressC..Thereare many waystogetDB2 but the easiest isfromthe
websiteat DB2ExpressCDataServer
InstallIBMDB2ExpressC.
Installeasy_install,whichisfoundhere:PythonSetupTools
Using the latter,installtheIBMDBegg,animplementation ofthePythonDBAPI2.0sothatwecan
interfacewithDB2 usingPython.You can downloaditfrom http://code.google.com/p/ibmdb/ (Take
note: Do not download the IBMDB egg forDjangobutrathertheIBMDB egg.Inour casesince
wereusingPython2.6,thefilenamelookssomethinglikeibm_db1.0.3py2.6win32.egg)

7.3Settingup
Go to the command processor. You should see thisscreenonceyouarethere (yourDB2 version maybe
different):

Next,letscreateadatabase:
db2=>createdatabasesample
DB20000ITheCREATEDATABASEcommandcompletedsuccessfully.

Connecttothedatabasewejustmade.
db2=>connecttosample
DatabaseConnectionInformation

Databaseserver =DB2/NT9.7.2
SQLauthorizationID=JOSE
Localdatabasealias=SAMPLE

Letsnowcreateatable:
db2=>createtablestudent(idsmallintnotnull,
last_namevarchar(100),
given_namevarchar(100),
login_namevarchar(100),
year_levelsmallint,
birthdaydate,
home_addressvarchar(100))

DB20000ITheSQLcommandcompletedsuccessfully.

Note: Anytableyoucreatewillhaveyouruseridaddedtothefrontasaschemaname. Forexample,ifyou


were logged in using the username Zaphod,your studenttable would have thefullnameZaphod.student
Alternatively,youcanspecifyaschemanamewhenyoucreateyourtable,e.g.:
createtabledent.student
SomeotherdatatypesinIBMDB2areshowninthepicturebelow:

Weneedjustonemoresteptocompleteoursetup.Letspopulateourdatabasewithrows:

db2=>INSERTINTOstudentVALUES(1,'Asuncion','Jose',
'jasuncion',2,'19880408','Manila')

DB20000ITheSQLcommandcompletedsuccessfully.

db2=>INSERTINTOstudentVALUES(1,'Delgado','Dan',
'dcdelgado',4,'19880420','Manila')

DB20000ITheSQLcommandcompletedsuccessfully.

Ifwewantedtopopulateourdatabasewithmanyvaluesatatime,allwehavetodois:

db2=>INSERTINTOstudentVALUES(3,'Duffy','Arthur','aduff',4,
'19890815','Bulacan'),(4,'Watson','Emilie','eawatson',5,'1987315',
'Singapore')
DB20000ITheSQLcommandcompletedsuccessfully.

7.4UsingIBMDB2withPython
Now thatwe are all set up, its timetohit the database!TobeabletouseIBMDB2withPythonwehave to
followsomesimplesteps:

ImporttheDB2moduleandconnecttothedatabase

Getaconnectionobject

Createacursor

PerformSQLqueries

Closethecursorandtheconnection

7.5ConnectionObjects

ThefirststepinaccessingaDB2databaseistoimporttheIBMDB2Pythonmodulethatwehaveinstalled.

>>>importibm_db

Then,weestablishaconnectiontoaparticulardatasource.

>>>ibm_db_conn=ibm_db.connect("sample","yourname","yourpassword")

Theconnect()constructoracceptsthefollowingparameters:
dsndatasourcename,requiredinourexampleourdatasourceisthedatabasewecreated
uidusername,required
pwdpassword,required

Thisissimilartowhenweconnectedtothedatabaseinthecommandlineprocessorinanearliersection:

Afterthatletusretrieveaconnectionobject:

>>>importibm_db_dbi
>>>conn=ibm_db_dbi.Connection(ibm_db_conn)
>>>

7.6CursorObjects

Onceyouhaveaconnectiontothedatabase,youcanuseittoretrieveacursor.

>>>cursor=conn.cursor()

A cursor makes us work with the IBM DB2 database. For example, ithasmethods whichwilltake in our
SQLSTATEMENTS(SELECT,INSERT,UPDATE, DELETE,CREATE,DROP,ALTER)asaparameterand
sendthemtothedatabase.Wewilldiscusstheseinmoredetailinthenextsection.

7.7PerformingSQLqueries

Beforewestart,letusfirstaddthismethoddefinitiontothenamespace.

>>>defprintrows(rows):
forrowinrows:
out=""
fordatainrow:
out+=str(data)+''
printout

7.7.1SELECT
The first thing that comes to mind regarding SQL is the SELECT statement. Let us get startedwithit in
Python! Use the same session thatweusedinthesetuppart.Ifyouhavealreadyclosedthatsession, open
anewoneandthenmakeanewconnection.

>>>cursor.execute("select*fromstudent)
>>>rows=cursor.fetchall()

The cursorsexecute() method takes inour SELECT statement andsends ittothedatabase.Thefetchall()


method getsallthe possiblerowsthatmatchesourquery.Finally,wecanoutputtothescreentheresultsof
ourquery:

>>>printrows(rows)

1AsuncionJosejasuncion219880408Manila
2DelgadoDandcdelgado419880420Manila
3LacanilaoArturoaclacanilao419890815Bulacan
4WatsonEmilieeawatson519870315Singapore
>>>

Youcanusethe
fetchone()
methodtogettherowsonebyone:

>>>whileTrue:
... row=curs.fetchone()
... ifrowisNone:
... break
... printrow

What this doesis tostart from the first row oftheresultsetandthegivetheoptiontoiterateoverthewhole


resultsetonebyonewhichisessentiallystoredinalist.

If you want, a parameter can specify the number of rows you want to retrieve by adding a numerical
parametertothe fetchone() method.

>>>rows=cursor.fetchmany(3)
>>>printrows(rows)

1AsuncionJosejasuncion219880408Manila
2DelgadoDandcdelgado419880420Manila
3LacanilaoArturoaduff419890815Bulacan

Maybeyouwouldliketoaddafiltertothequery.Justconstructanewqueryasastring.

>>>query2="select*fromartistswherelast_name='Asuncion'
>>>cursor.execute(query2)
>>>rows=cursor.fetchall()
>>>print(rows)
1AsuncionJosejasuncion219880408Manila
>>>

7.7.2INSERT
TheINSERTstatementisusedtoaddmorerowsintoatable.

Naively,thefollowingmethodworks:

>>>cursor.execute("INSERTINTOstudentVALUES
(1,'Webb','Ryan','rgwebb',5,'1071984','London')")

Let ustake that a stepfurther and save ourselves some typingspace so wedonthavetokeyinthewhole
cursor.execute(... line of code whenever we want to do an insert. By using dictionaries we can pass a
wholerowasaparametertoourPythoninsertstatement:

>>>new_entry=(6,"Man","Spider","scparker",5,"199011","NewYork")
>>>cursor.execute("insertintostudentvalues(?,?,?,?,?,?,?)",new_entry)

Alternatively, we caninsertmultiple rows in a single execute() call.However, insteadofusingtheexecute()


method,wewillusetheexecutemany()method.Letsdothat:

Wemakeupalistofsampledatatoinsert.

>>>list=[(i,Lastname,Firstname,lgname,i,112010,Hometown)
foriinrange(10,15)]

Weformthequeryandthefeeditaswellasthelisttothecursorsexecutemany()method:

>>>insert_sql=INSERTINTOstudentVALUES(?,?,?,?,?,?,?)
>>>cursor.executemany(insert_sql,list)

Checktoseeifallthevalueswereinsertedbyrunninga
SELECT*
queryfromthedatabase.

7.8Exercises

1.Createaprogramthatallowsauserto
CreateSection
Addalistofstudentsandsavetothedatabase
ViewSections
Viewalistofstudentsinasection
Addastudent/stoasection
Removeastudentfromasectionandupdatethedatabase

2. Using the format()function discussedin chapter 3and the namedtuple functiondiscussedinchapter 4,


write a Python program that will access the student table created in the example and produce a tabular
reportwithcolumnheadingsandalldataleftaligned.

AppendixASolutionstothereviewquestions
A
Chapter2
1. a.
y=2*3

b.if4==2/2:#Checkif4isequalto2/2
print"4=2/2!"

c.forxin1,2,3:#printthefirstthreepositiveintegers
printx

d.x=4ifbelsex#assign4toxifbisTrue
or

ifb:x=4
e.whileTrue:
x=1
ifx:continue#indentationmustbethesame

2.n=5
a,b=0,1
foriinrange(n):
a,b=b,a+b
printa

3.
xx**3/(3*2*1)+x**5/(5*4*3*2*1)x**7/(7*6*5*4*3*2*1)+
x**9/(9*8*7*6*5*4*3*2*1)x**11/(11*10*9*8*7*6*5*4*3*2*1)

4.
m=6
months=(
('January','Garnet')
,('February','Amethyst')
,('March' ,'Aquamarine')
,('April' ,'Diamond')
,('May' ,'Emerald')
,('June' ,'Alexandrite')
,('July' ,'Ruby')
,('August','Peridot')

,('September','Sapphire')
,('October','Tourmaline')
,('November','Topaz')
,('December','Zircon')
)
print'Month{0}is{1}andit''sbirthstoneis{2}'\
.format(m,months[m1][0],months[m1][1])

Chapter3
1.
deffib_binet(n):
ifn==0:return0
phi=(1+math.sqrt(5))/2
F=int(math.floor(phi**n/math.sqrt(5)+.5))
returnF
2.
defcoroutine(func):
defstart(*args,**kwargs):
cr=func(*args,**kwargs)
cr.next()
returncr
returnstart

3.
defpywalk(dir):
"""
os.Walk(top)Foreachdirectoryinthetreerootedatdirectory
topityieldsa3tuple
(dirpath,dirnames,filenames).
"""

for(_,_,filenames)inos.walk(dir):
forfilenameinfilenames:
iffilename.endswith('.py'):
yieldfilename

#Exampleusage
forfilenameinpywalk(sys.path[7]):printfilename

4.(a)
frombisectimportbisect_left
deflistops(l,item,operation):
ifnotisinstance(l,list):
raiseTypeError('Firstargumentisnotalist')
ifoperation==0:
l.sort()
elifoperation==1:
i=bisect_left(l,item)
l.insert(i,item)
returni==len(l)orl[i+1]==item
elifoperation==2:
i=bisect_left(l,item)
ifi<len(l)andl[i]==item:
dell[i:i+1]
returnTrue
else:
returnFalse
elifoperation==4:
i=bisect_left(l,item)
ifi<len(l)andl[i]==item:
returnTrue
else:
returnFalse
4.(b)
defc0(l,item):returnlistops(l,item,0)
defc1(l,item):returnlistops(l,item,1)
defc2(l,item):returnlistops(l,item,2)
defc4(l,item):returnlistops(l,item,4)

4.(c)
fromfunctoolsimportpartial
mylistops=partial(listops,mylist)

Chapter4
1.
importsys
importos

fromcollectionsimportdefaultdict

mydict=defaultdict(list)
forpathinsys.path:
ifpath=='':continue #ignoreemptypaths

#handleWindowsdrives
ifpath[0].isalpha()andpath[1]==':':
drive,path=path.split(':')
drive+=':'
else:
drive=''

#assembleprefixfordirectorywalk
prefix=drive+os.sep.join(path.split(os.sep)[:3])

#Directorywalk
fordirpath,dirnames,_inos.walk(prefix):

#Processsubdirectoriesreturned
forsuffixindirnames:
#assemblefullpath
subdir=(os.sep.join([dirpath,suffix]))

#removeprefixandaddtodict
subdir=subdir[len(prefix)+1:]
mydict[prefix].append(subdir)

#printtheresults
forprefixinsorted(mydict):
printprefix
forsuffixinsorted(mydict[prefix]):
print''+suffix
2.(a)
defmovies(md):
#Getmovietitleanddirectorname
whileTrue:
movie_name=raw_input('Movienameandyear:')
ifmovie_name=='':break
director=raw_input('Directorname:')

ifdirector=='':break

#Getcastmembers
cast=[]
whileTrue:
cast_member=raw_input('Castmember:')
ifcast_member=='':break
cast.append(cast_member)
md[movie_name]=(director,tuple(cast))

2.(b)
defmoviestar(md,star):
#Buildlistofmoviesstarhasbeenin
movie_list=[]
formovie,(director,cast)inmd.iteritems():
ifany(star==cast_member.split('')[1]
forcast_memberincast):
movie_list.append(movie)

#Printthelistofmovies
formovieinmovie_list:
print'Title:'+movie
print'Director:'+md[movie][0]
print'Cast:'+md[movie][1][0]
forcast_memberinmd[movie][1][1:]:
print''+cast_member
print

3.(a)
fromrandomimportrandom
defbuildarray(rows,cols,min,max):
array=\
[
[min+random()*(maxmin)for_inrange(cols)]
for_inrange(rows)
]
returnarray

3.(b)
defmatrix_mult(A,B):
ifnotall(len(col)==len(A[0])forcolinA[1:]):

raiseValueError,'ArrayAisnotrectangular'
ifnotall(len(col)==len(B[0])forcolinB[1:]):
raiseValueError,'ArrayBisnotrectangular'
iflen(A)<>len(B[0]):
raiseValueError,'Arrayscannotbemultiplied'

AB=[[0for_inxrange(len(A))]for_inxrange(len(A))]
fori,jin((i,j)foriinxrange(len(AB))
forjinxrange(len(AB))):
AB[i][j]=sum(A[i][k]*B[k][i]
forkinxrange(len(B)))
returnAB

Chapter6

1.
classSection:
id=0
title=''
instructor=''
students=[]

def__init__(self,id,title,instructor,students):
self.id=id
self.title=title
self.instructor=instructor
self.students=students

2.
classInstructor:
name=''
subjects=[]

def__init__(self,name,subjects=[]):
self.name=name
self.subjects=subjects

3.Addclassmethod:

def__contains__(self,name):
returnnameinself.students

4.Addclassmethods:

defadd(self,name):
self.students.append(name)

defsize(self):
returnlen(self.students)

5.Addclassmethod:

def__iter__(self):
forstudentinself.students:
yieldstudent

Chapter7
1.
#importneededmodules
importibm_db
importibm_db_dbi

#connecttodatabaseandgetcursorobject
cibm=ibm_db.connect('sample','youruserid','yourpassword')
conn=ibm_db_dbi.Connection(cibm)
curs=conn.cursor()

#DefineCREATEcommandforSectiontable
create_section="""
CREATETABLESection(
IdINTEGERGENERATEDALWAYSASIDENTITY
,titlevarchar(50)
,instructorvarchar(50)
,studentvarchar(50))

"""
#CreateSectiontable
curs.execute(create_section)

#DefineINSERTINTOcommandforSectionTable
insert_section="""
INSERTINTOSection(title,instructor,student)VALUES

(?,?,?)
"""

#InsertstudentsintoSectiontable
title='GettingstartedwithPython'
instructor='GeraldandJose'
students=('Bob','Carol','Ted','Alice')

forstudentinstudents:
curs.execute(insert_section,(title,instructor,student))

#Viewsections

curs.execute('SELECT*FROMSection')
forrowincurs.fetchall():
printrow

#Viewstudentsinasection
curs.execute(
'SELECTstudentFROMSectionWHEREtitle=?',
[title])
forstudentincurs.fetchall():
printstudent

#Addstudentstoasection
new_students=('Frodo','Bilbo','Gandalf','Galadriel')
forstudentinnew_students:
curs.execute(insert_section,(title,instructor,student))

#Removestudentfromasection
curs.execute(
'DELETEFROMSectionWHEREtitle=?ANDStudent=?',
[title,'Bob'])

2.
#Formattedoutput
fromcollectionsimportnamedtuple
StudentRow=namedtuple('StudentRow','ID,LAST_NAME,
GIVEN_NAME,LOGIN_NAME,YEAR_LEVEL,BIRTHDAY,HOME_ADDRESS')

curs.execute('SELECT*FROMSTUDENT')


row_format='{0:>2}{1:<12}{2:<12}{3:<12}{4:>4}{5:>10}
{6:<12}'
printrow_format.format(
'ID','LAST_NAME','GIVEN_NAME','LOGIN_NAME','YEAR',
'BIRTHDAY','HOME_ADDRESS'
)

row_format='{0:>2}{1:<12}{2:<12}{3:<12}{4:>4}{5!s:>10}
{6:<12}'

forstuinmap(StudentRow._make,curs.fetchall()):
printrow_format.format(
stu.ID,stu.LAST_NAME,stu.GIVEN_NAME,
stu.LOGIN_NAME,stu.YEAR_LEVEL,stu.BIRTHDAY,
stu.HOME_ADDRESS
)

conn.close()

References
[1] ZIKOPOULOS, P. IBM DB2 Universal Database and the Microsoft Excel Application
Developer for Beginners, dbazine.com article, April 2005
http://www.dbazine.com/db2/db2disarticles/zikopoulos15
[2] ZIKOPOULOS, P. DB2 9 and Microsoft Access 2007 Part 1: Getting the Data...,
Database Journal
article,May2008
http://www.databasejournal.com/features/db2/article.php/3741221
Use Microsoft Access to interactwithyourDB2data
[3] BHOGAL, K. , developerWorks article,May2006.
http://www.ibm.com/developerworks/db2/library/techarticle/dm0605bhogal/
[4] CHUN, J., CIRONEP. DB2 packages:Concepts,examples,andcommonproblems , developerWorks
article,June2006http://www.ibm.com/developerworks/data/library/techarticle/dm0606chun/index.html
[5] CHEN WheiJen et all.
DB2 ExpressC: The Developer Handbookfor XML,PHP,C/C++,Java,and
.NET August2006SG24730100 http://www.redbooks.ibm.com/abstracts/sg247301.html?Open

Resources
Websites

1. DB2ExpressCwebsite:
www.ibm.com/db2/express
Use this web site to download the image for DB2 ExpressC servers, DB2 clients, DB2 drivers,
manuals,accesstotheteamblog,mailinglistsignup,etc.

2. DB2ExpressCforum: www.ibm.com/developerworks/forums/dw_forum.jsp?forum=805&cat=19
Usetheforumtoposttechnicalquestionswhenyoucannotfindtheanswersinthemanualsyourself.

3. DB2InformationCenter
http://publib.boulder.ibm.com/infocenter/db2luw/v9/index.jsp
The information center provides access to the online manuals. It is the mostup todate source of
information.

4. developerWorks
http://www128.ibm.com/developerworks/db2
This Web site isan excellentresource for developers andDBAsprovidingaccesstocurrentarticles,
tutorials,etc.forfree.

5. alphaWorks
http://www.alphaworks.ibm.com/
This Web site providesdirect accesstoIBM'semerging technology. Itis a place whereone can find
thelatesttechnologiesfromIBMResearch.

6. planetDB2
www.planetDB2.com
ThisisablogaggregatorfrommanycontributorswhoblogaboutDB2.

7. DB2TechnicalSupport
If you purchased the12 months subscription licenseofDB2 ExpressC, you can downloadfixpacks
fromthisWebsite.
http://www.ibm.com/software/data/db2/support/db2_9/

8. ChannelDB2
ChannelDB2 is a social network for the DB2 community. It features content such as DB2 related
videos, demos, podcasts, blogs, discussions, resources, etc. for Linux, UNIX, Windows, z/OS,and
i5/OS.
http://www.ChannelDB2.com/

Books
1. FreeRedbook:DB2ExpressC:TheDeveloperHandbookforXML,PHP,C/C++,Java,and.NET
WheiJenChen,JohnChun,NaomiNgan,RakeshRanjan,ManojK.Sardana,
August2006SG24730100
http://www.redbooks.ibm.com/abstracts/sg247301.html?Open

2. UnderstandingDB2LearningVisuallywithExamplesV9.5
RaulF.Chong,etall.January2008
ISBN10:0131580183

3. DB2 9: pureXMLoverview andfaststart byCynthiaM.Saracco,Don Chamberlin, RavAhujaJune
2006SG247298
http://www.redbooks.ibm.com/abstracts/sg247298.html?Open

4. DB2 SQL PL: Essential Guide for DB2 UDB on Linux, UNIX, Windows, i5/OS, and
z/OS,2ndEdition
ZamilJanmohamed, Clara Liu, Drew Bradstock,RaulChong, Michael Gao, Fraser McArthur, Paul
Yip
ISBN:0131007726

5. FreeRedbook:DB2pureXMLGuide
WheiJenChen, Art Sammartino,DobromirGoutev,FelicityHendricks,IppeiKomi,MingPangWei,
RavAhuja,MatthiasNicola.August2007
http://www.redbooks.ibm.com/abstracts/sg247315.html?Open

6. InformationonDemandIntroductiontoDB29NewFeatures
PaulZikopoulos,GeorgeBaklarz,ChrisEaton,LeonKatsnelson
ISBN10:0071487832
ISBN13:9780071487832

Contactemails
GeneralDB2ExpressCmailbox:
db2x@ca.ibm.com
GeneralDB2onCampusprogrammailbox:
db2univ@ca.ibm.com

Getting
started
with
DB2 application development
couldn't
be
easier.

Read this book to:



Discover DB2 application development using DB2 Express-C

Write SQL, XQuery, and understand pureXML technology
Learn how to develop DB2 stored procedures, functions and data
Web services
Learn how to work with DB2 and Java , C/C++, .NET, PHP, Ruby on
TM

Rails, Perl, and Python


Troubleshoot DB2 database-related problems
Practice
with hands-on e xercises

DB2 Express-C from IBM is the no-charge edition of DB2 data server for managing
relational and XML data with ease. No-charge means DB2 Express-C is free to
download, free to develop your applications, free to deploy into production, and even
free to embed and distribute with your solution. And, DB2 does not place any
artificial limits on the size of databases, number of databases, or number of users.


DB2 Express-C runs on Windows , Linux , Solaris, and Mac OS X systems, and
provides application drivers for a variety of programming languages and frameworks
including C/C++, Java, .NET, Ruby on Rails, PHP, Perl, and Python. If you require
even greater scalability or more advanced functionality, you can seamlessly deploy
applications built using DB2 Express-C to other DB2 editions such as DB2 Workgroup
and DB2 Enterprise.

This free edition of DB2 is ideal for developers, consultants, ISVs, DBAs, students, or
anyone who intends to develop, test, deploy, or distribute database applications.
Join the growing DB2 Express-C user community today and take DB2 Express-C for
a test drive. Start discovering how you can create next generation applications and
deliver innovative solutions.

To learn more or download DB2 Express-C, visit


ibm.com/db2/express

To socialize and watch related videos, visit


channelDB2.com

This book is part of the DB2 on Campus book series, free eBooks for the community.
Learn more at db2university.com

Você também pode gostar