MIME-Version: 1.0 Content-Location: file:///C:/F48430D5/Week5.htm Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset="us-ascii"
Week =
5
Variables, Decision Structures, and Exceptions
Computer Science A202 /
A598
and Informatics I211
This
week’s success strategy
<=
![if !supportLists]>n If
you are having trouble solving a problem, notice what problem solving techn=
ique
you are using
<=
![if !supportLists]>q <=
/span>could you use it better?
<=
![if !supportLists]>q <=
/span>would it be better to use another technique?
<=
![if !supportLists]>n&nb=
sp;
A very general and powerful problem solving
technique: break big problems up into smaller problems
<=
![if !supportLists]>q <=
/span>develop and test programs incrementally
<= ![if !supportLists]>q <= /span>for difficult debugging, save a copy of the progra= m and then start removing code to simplify things until the problem is isolated.<= o:p>
This =
week
<=
![if !supportLists]>n Variables
<=
![if !supportLists]>q <=
/span>parameter passing
<=
![if !supportLists]>q <=
/span>aliasing
<=
![if !supportLists]>q <=
/span>global variables
<=
![if !supportLists]>n if
statement
<=
![if !supportLists]>q <=
/span>boolean expressions
<=
![if !supportLists]>n Raising
exceptions
Param=
eter
passing is by-value
<=
![if !supportLists]>n Only
the value of an actual parameter is passed to a function
<=
![if !supportLists]>q <=
/span>assigning a new value to a parameter variable chan=
ges
only that variable
<=
![if !supportLists]>q <=
/span>if a variable is the actual parameter of the call =
to
the current function, its value is not affected by the assignment
>>> x =3D 2
>>> def fun(y):
y =3D 3
>>> fun(x)
>>> x
2
<=
![if !supportLists]>q <=
/span>it works like this in most, but not all, languages=
Alias=
ing
<=
![if !supportLists]>n In
English, alias means an alternate name
<=
![if !supportLists]>n In
programming, aliasing occurs whenever there is more than one =
way
to access an object or data structure
<=
![if !supportLists]>q <=
/span>mutable objects may be changed through an alias
>>> lst1 =3D [1]
>>> lst2 =3D lst1
>>> lst2[0] =3D 3
>>> lst1
[3]
Alias=
ing
of parameters
<=
![if !supportLists]>n When
a function's actual parameter is a variable reference, the corresponding fo=
rmal
parameter becomes an alias for the actual parameter.
<=
![if !supportLists]>q <=
/span>So though assignments to a formal parameter do not
change any other variable, assignment to part of a data structure passed as=
an
argument will be visible to the caller
>>> def fun(lst2):
lst2[0] =3D 5
>>> fun(lst1)
>>> lst1
[5]
Global
variable assignment
<=
![if !supportLists]>n =
span>(This is not in your text)
<=
![if !supportLists]>n =
span>A global variable is one that is not local =
to a
function (or class)
<=
![if !supportLists]>n =
span>A variable must be declared global before it can be
assigned from within a function
>>> x =3D 0
>>> def fun():
global x # note =
use of
keyword global
x =3D 3
>>> fun()
>>> x
3
>>> def fun():
x =3D 5
>>> fun()
>>> x
3
<=
![if !supportLists]>n =
span>Global variables do not need to be declared if they
are only referenced (not assigned)
One-a=
rmed
if statement
<=
![if !supportLists]>n Syntax:
if <test expression> :
<then block>
<=
![if !supportLists]>q <=
/span><block> is a sequence of statements (general=
ly
indented)
<=
![if !supportLists]>n
in Python documentation=
a
block is called a suite
<=
![if !supportLists]>n Semantics
(meaning): <then block> is executed only if <test expression> f=
irst
evaluates to a true value
<=
![if !supportLists]>n A true
value is any value other than the false values: None, False, zero
(of any numeric type), any empty sequence, or any empty dictionary (=
we
haven't see dictionaries yet)
>>> if 'abc'[1:-5]: # ''
print 3
>>>
Two-a=
rmed
if statement
<=
![if !supportLists]>n Syntax:
if <test expression> :
<then block>
else:
<else block><=
o:p>
<=
![if !supportLists]>n Semantics:
if <test expression> evaluates to a true value, execute <then
block>, and otherwise execute <else block>
One- =
and
two-armed if flow charts
If
statement examples
<=
![if !supportLists]>n One-
and two-armed if statements in functions equivalent to the built-in abs<=
/b>
function
def oneArmedAbs1(x): def
oneArmedAbs2(x):
if x <=
0: &=
nbsp; if x < 0:
return -x =
x =3D -x
return x<=
span
style=3D'mso-spacerun:yes'> =
return x
def twoArmedAbs(x):
if x <=
0:
return -x
else:
return x
<=
![if !supportLists]>n Which
is better style, and why?
Gener=
al if
statement with elif
<=
![if !supportLists]>n =
span>Syntax:
if <test expression> :
<then block>
elif
<test expression> :
<then block>
…
[e=
lse:
<else
block>]
<=
![if !supportLists]>q
read elif as =
or
else, if
<=
![if !supportLists]>q <=
/span>As usual in syntactic notation, square brackets indicate their conte=
nts
is optional and ellipsis "…" indicates the preceding
syntactic element may be repeated any number of times (including zero)
<=
![if !supportLists]>n =
span>Semantics: evaluate <test expression>s in or=
der
until one is true, and then execute the associated <then block>. If no
<test expression> is true, execute <else block> if it is presen=
t
Else-=
if
flow chart
Else-=
if
example
<=
![if !supportLists]>n =
span>The following both implement the mathematical sign
function
def signWithElif(x):
if x <=
0:
return -1
elif x =
=3D=3D 0:
return 0
else: # x=
>
0
return 1
def signWithoutElif(x):
if x <=
0:
return -1
else:
if x
=3D=3D 0:
=
return 0
else: # x > 0
=
return 1
Exerc=
ise:
ordinal suffix
<=
![if !supportLists]>n &nb=
sp; The ordinal suffix of 1, 2, and 3 is st, nd, and rd=
,
respectively, while that of integers larger than 3 is th.
<=
![if !supportLists]>n &nb=
sp; Define the function ordinalSuffix(n) that returns the ordinal
suffix of n (assuming n is a positive integer).
<=
![if !supportLists]>n &nb=
sp; Two solutions:
def ordinalSuffix(n):
if n =3D=
=3D 1:
return 'st'
elif n =
=3D=3D 2:
return 'nd'
elif n =
=3D=3D 3:
return 'rd'
else:
return 'th'
def ordinalSuffix2(n):
if n <=
4:
return ['st', 'nd', 'rd'][n-1]
else:
return 'th'
Test
expressions
<=
![if !supportLists]>n In
Python any expression may be used as a test expression, since all values are
interpreted as true or false
<=
![if !supportLists]>n The
literals True and False, of type bool, are represent t=
he
boolean values true and false
<=
![if !supportLists]>n A predicate
is a function that returns a boolean value
>>> callable(open)
True
>>> callable(3)
False
Relat=
ional
operators
<=
![if !supportLists]>n The
relational operators are also predicates
<=
![if !supportLists]>q
< <=
span
style=3D'font-size:10.0pt;font-family:Arial;mso-bidi-font-family:Arial;
mso-bidi-language:#AC45'>means less than
<=
![if !supportLists]>q
<=3D =
b>means less than or equal
<=
![if !supportLists]>q
> means greater than
<=
![if !supportLists]>q
>=3D =
b>means greater than or equal
<=
![if !supportLists]>q
=3D=3D means equal (do not confuse with =3D)
<=
![if !supportLists]>q <=
/span>!=3D means=
not
equal
<=
![if !supportLists]>q
is (is not) test if values are (are no=
t)
the same
<=
![if !supportLists]>q <=
/span>in (n=
ot
in) test sequence (non-)membership
<=
![if !supportLists]>n &nb=
sp; <value> in <sequence> is true if <value>=
is
=3D=3D to some element of the sequence
<=
![if !supportLists]>n &nb=
sp; example: 'b' in 'abc' and 2 not in [1, 3] are true
Order=
ing
of all things
<=
![if !supportLists]>n =
span>The ordering operators (<, <=3D, >, &g=
t;=3D)
can be used to compare any two value
<=
![if !supportLists]>n =
span>They reflect the usual ordering of numbers, but how
are other values ordered?
<=
![if !supportLists]>n =
span>Characters are ordered by the ordinal values
<=
![if !supportLists]>q <=
/span>returned by the ord function
<=
![if !supportLists]>n =
span>Sequences of the same type are ordered lexicogr=
aphically
<=
![if !supportLists]>q <=
/span>the order is determined by the first pair of corresponding elements =
that
are not equal
<=
![if !supportLists]>q <=
/span>this gives the usual alphabetical ordering on strings
>>> ['Month' < 'Monty',
'ABC' < 'Aa',
(1, 'Z', 3) < (1, 'a', 3)=
]
[True, True, True]
<=
![if !supportLists]>n &nb=
sp; Object classes can have methods that determine the order of their
instances
Equal=
ity
and sameness
<=
![if !supportLists]>n Numbers
are equal only when they are the same, but is this true of all
values, such as sequences?
<=
![if !supportLists]>n Two
sequences are the same if they are the same object, but equal if they are t=
he
same type of sequence and corresponding elements are equal
<=
![if !supportLists]>n (transcript)
<=
![if !supportLists]>n Two
object references are the same if they refer to the same location in memory,
but if they are instances of the same class they are equal if their classes
__eq__ method says they are
Exerc=
ise
<=
![if !supportLists]>n Define
a function that takes a number from 1 through 12 and returns the number of =
days
in the corresponding month, ignoring leap years
<=
![if !supportLists]>n Answer
def daysInMonth(month):
if month =
in [9,
4, 6, 11]:
return 30
elif mont=
h =3D=3D
2:
return 28
else:
return 31
Contr=
olling
execution when importing
<=
![if !supportLists]>n The
variable __name__ contains the name of the module if the module is
imported, and '__main__' if the module is run as an application
<=
![if !supportLists]>n It
is customary for application modules to end with the following, rather than
just a main() call
if __name__ =3D=3D '__main__':
main()
<=
![if !supportLists]>n Why
might the advantage of this be?
<=
![if !supportLists]>n It
allows the module to be imported so its functions can be tested or otherwise
used without of running the application
Excep=
tions
raised by the system
<=
![if !supportLists]>n =
span>We say an exception has been raised when the
system detects an error that results in the program terminating with a mess=
age
indicating the nature of the error and traceback telling us where it occurr=
ed
>>> 'abc'[3]
Traceback (most recent call last):
File
"<pyshell#29>", line 1, in -toplevel-
'abc'[3]<= o:p>
IndexError: string index out of range
>>>
<=
![if !supportLists]>n =
span>What are other situations in which Python raises an
exception?
<=
![if !supportLists]>n =
span>Partial answer
<=
![if !supportLists]>q <=
/span>trying to open a file that does not exist
<=
![if !supportLists]>q <=
/span>dividing by zero
<=
![if !supportLists]>q <=
/span>sending a message to a value that is not an object or an object that
does not have the indicated method
<=
![if !supportLists]>q <=
/span>trying to call a value that is not a function
<=
![if !supportLists]>q <=
/span>passing math.sqrt a negative number
Excep=
tions
in program execution
<=
![if !supportLists]>n Programs
rely on may aspects of their data and operating environment that may not be
true due to
<=
![if !supportLists]>q <=
/span>errors in other parts of the program
<=
![if !supportLists]>q <=
/span>errors or exceptional situations in the data fed to
the program, or
<=
![if !supportLists]>q <=
/span>failures in the supporting computing environment
<=
![if !supportLists]>n If
a program fails to check for such exceptional situations, it may produce bo=
gus
results or "blow up" with an exception raised by the system that =
the
user of the program is unable to interpret
<=
![if !supportLists]>q <=
/span>In some other languages (such as C and C++) such
errors may cause the program, or even the entire computer, to "crash" without even =
giving
a message, but Python is designed to prevent this
Robust
programs  =
;
<=
![if !supportLists]>n&nb=
sp;
Programs that check for errors and exception=
al
situations and give meaningful error messages and when possible take measur=
es
to recover from exceptional situation are said to be robust
<=
![if !supportLists]>n Robustness
is one of the most important aspects of program quality
<=
![if !supportLists]>q <=
/span>Making a robust program can be several times as mu=
ch
work as writing an otherwise similar fragile (non-robust) program
<=
![if !supportLists]>q <=
/span>It is estimated that 80-90% of the instructions in
commercial programs is there just to make the program robust
<=
![if !supportLists]>n Small
programs used only occasionally by a few&n=
bsp;
knowledgeable users generally need not be very robust
<=
![if !supportLists]>q <=
/span>but even then some error checking is generally
worthwhile because it makes debugging easier
Deali=
ng
with exceptions
<=
![if !supportLists]>n Bad
data or other exceptional circumstances generally mean the program cannot
continue in its ordinary way, so what should it do?
<=
![if !supportLists]>n Many
applications just prints an error message and terminate appropriately
<=
![if !supportLists]>n What
should a function written for use in a variety of situations in other progr=
ams
do?
<=
![if !supportLists]>n Answer:
let the calling program decide how to deal with the problem by either
<=
![if !supportLists]>q <=
/span>returning a value indicating an error or failure of
some kind
<=
![if !supportLists]>n &nb=
sp; example: string.find returns -1 if the substring is not found=
<=
![if !supportLists]>q <=
/span>raising an exception
Raisi=
ng
exceptions
<=
![if !supportLists]>n The
raise statement raises or throws an exception, which m=
ay
be any value
<=
![if !supportLists]>q <=
/span>syntax: raise <exception value
expression>
<=
![if !supportLists]>q <=
/span>a string containing an appropriate error message is
the simplest kind of useful exception value
<=
![if !supportLists]>n Unless
the exception is caught by a program try statement, the progr=
am
will terminate
<=
![if !supportLists]>q <=
/span>in most contexts (such as applications) terminatio=
n is
indicated with a traceback message indicating where the exception was raised
followed by the printed form of the exception value
<=
![if !supportLists]>q <=
/span>the traceback message indicates all the function c=
alls
that had been made but not returned at the time the exception was raised
Probl=
em:
improving the daysInMonth function
<=
![if !supportLists]>n Modify
daysInMonth program so it raises an exception if the month number is=
not
an integer from 1 through 12.
>>> daysInMonth(12)
31
>>> daysInMonth(13)
Traceback (most recent call last):
File
"<pyshell#4>", line 1, in -toplevel-
daysInMon=
th(13)
File
"C:\home\202\c\5\misc.py", line 31, in daysInMonth
raise 'Bad
month: ' + str(month)
Bad month: 13
>>>
<= o:p>
Bette=
r daysInMonth
function
<=
![if !supportLists]>n Solution:
def daysInMonth(month):
if month =
not in
range(1,13):
raise 'Bad month: ' + str(month)
if month =
in [9,
4, 6, 11]:
return 30
elif mont=
h =3D=3D
2:
return 28
else:
return 31
<=
![if !supportLists]>n It
is often helpful to include the offending value in the error message
<=
![if !supportLists]>q <=
/span>This can cause problems if the value is a huge data
structure with a string representation that goes on for pages!