Oct 6
Discuss homework.
function tricks
Also, examples of the global vs local vs return vs print
issues that I discussed last time are given in
function_tricks.py
which I encourage you to look over and to ask
questions about as needed.
Quick quiz on "print" vs "return". Given this python code,
def square(x):
return x**2
def print_square(x):
print x**2
a = 3 # define a number
which of these four statements do something reasonable?
square(a)
b = square(a)
print_square(a)
b = print_square(a)
for the good of the order
I've posted the assignments through the end of October.
- Next week (Oct 13) is one on conditionals, and a proposal for a project, due in two weeks.
- The week after (Oct 20) is Hendrick's days - no class and no assignment due.
- The midterm project is due the week after (Oct 27), and is the only thing due that week.
new business
OK, on to next topic: conditionals
(The rest this may well continue into Thursday's class - we'll see.)
decisions and booleans
This is both chap 7 and 8 material; you should read both
over the next week. (I'll be skipping around within both in what follows.)
if x < 7 :
print "x is small"
else :
print "x is big"
Draw as flow chart.
The "x < 7" is the part I want to talk about (pg 250 etc) in text.
We're now going to have programs that 'branch', which means that
different things can happen. The decision point is a fork in
the road, and which one happens is nearly always a True/False
choice using what are called 'booleans'.
what is 'truth' ?
To do conditionals, the program needs to branch on things like (3 > 4),
which have values of True or False. This is really a branch of
math called "Boolean algebra", and values of these sorts are called "booleans",
which in python have type 'bool'. The python values are (True, False).
>>> 4 > 3
True
>>> 4 < 3
False
>>> type( True )
<type 'bool'>
>>> type( 4 > 3 )
<type 'bool'>
Plain old arithmetic has binary operaters (that combine two numbers),
unary operations (that change one number), and values (the numbers themselves) :
arithmetic :
binary operation :
1 + 2 → 3 ; int OP int → int (infix)
unary operations :
- (1) → (-1) ; OP int → int (prefix)
5! → 120 ; int OP → int (postfix)
values: 1, 2, 3, ...
operators: +, -, *, !, ...
logic :
binary operation :
4 > 3 → True ; value OP value → bool
4>3 or 4<3 → True ; bool OP bool → bool
unary operations :
not True ===> False ; OP bool ===> bool (prefix)
values: True, False
operators: not, and, or, <, > , ==, >=, <=, is, ..
These can be combined in algebraic expressions :
not ( x or not y ) and (not y or z)
Logic has other structures that are not built into python :
if a then b
a implies b
a → b
In python, these comparisons on strings, lists, numbers give True or False :
a < b # less than ?
a <= b # less than or equal to ?
a > b # greater than ?
a >= b #
a == b # equal to ? (i.e. prints the same)
a != b # not equal to ? (i.e. prints different)
a is b # a and b different names for same memory object?
Unless you have a reason to, don't use 'is'; use '=='.
A common mistake: "if a = b: ...". The '=' there is
the assignment operator, not the test-for-equality operator.
Note also that just as int("1") will convert a string to the
corresponding number, bool(thing) will convert 'thing' - no
matter what type it is - into either True or False. Python
will do this automatically if you put something that isn't
a boolean somewhere where it expects a boolean test, like
in an "if" statement.
The conversion rules are essentially:
0, 0.0, "", [], (), None converts to False
anything else converts to True
Do some examples at the python command line,
looking at how other python types behave
when they are compared.
>>> a = [1,2,3]
>>> b = [1,2,3] # looks same; different memory address
>>> a == b # Do the look the same?
True
>>> a is b # Are they the same? (i.e. id(a) == id(b))
False
>>> "dog" > "cat" # alphabetic order
True
>>> [1,2,3] > [1,1,1] # left to right numeric sort
True
>>> bool("Hi there")
True
>>> bool(0)
False
>>> a = "Hello"
>>> if a: print "auto-convert a to bolean"
comparisons between types
Here's a weird thing :
$ python
>>> 1 < "Hello"
True
What's going on?
In python 3 this throws an error. (Which is what I would have expected.)
Different programming languages treat this issue in different ways.
Perl, for example, will turn 7 + "3 dogs" into 10.
Best practice: don't do that.
symbolic logic
Discuss uses of and definitions of 'and', 'or', 'not' in logic.
(1) Every one who is sane can do Logic;
(2) No lunatics are fit to serve on a jury;
(3) None of your sons can do Logic.
What conclusion can be drawn?
Use
a = able to do Logic
b = fit to serve on a jury
c = sane
d = your sons
Express each line as a boolean expression.
Use the rules of boolean algebra to draw a short conclusion.
Answer: None of your sons is fit to serve on a jury.
How can we do that using logic rules? python??
aside
python (and most programming languages) also have bitwise (as opposed to logical) operators, which treat an integer as a base 2 binary number, and combine the 1's and 0's as individual 'true' and 'false' values :
& bitwise and 0b1010 & 0b1100 = 0b1000
| bitwise or 0b1010 & 0b1100 = 0b1110
~ bitwise not ~ 0b10 = 0b01
^ bitwise xor 0b1010 & 0b1100 = 0b0110
Here 0b1010 is python's way of writing "1010 in binary", i.e. in base 2,
which in this case is (1,0,1,0) times the powers of two, (8, 4, 2, 1),
which is 8 + 2 = 10 in our regular decimal or base 10 system.
I don't expect to be using these this term.
details
Here are how the logic operations work :
a and b True only when both are True
a or b False only when both are False
not a Flip True/False value of 'a'
a → b implies
a ⇔ b if and only if
a xor b exclusive or
A 'truth table' shows explicitly what they all do.
a b (a and b) (a or b) (a => b) (a <=> b) (a xor b)
..............................................................
T T T T T T F
T F F T F F T
F T F T T F T
F F F F T T F
Some logic statements called 'syllogisms' are always True,
like identities in mathematics.
For example,
((a → b) and (b → c)) → (a → c)
which in English says
If a implies b, and b implies c, then a implies c.
These identities can all be verified by checking all the
possibilities explicitly with a truth table.
( a → b ) ⇔ (not a or b)
( a and b ) ⇔ not (not a or not b)
( a or b ) ⇔ not (not a and not b)
( not not a ) ⇔ a
( a or not a ) ⇔ True
a and (b and c) ⇔ (a and b) and c
a or (b or c) ⇔ (a or b) or c
a and (b or c) ⇔ (a and b) or (a and c)
a or (b and c) ⇔ (a or b) and (a or c)
a → b ⇔ (not b) → (not a)
In class: start writing a python program which prints out a truth table.
- First version: explicitly code everything.
- Second version: loop over True, False values.
- Third version: use some functions.
- Fourth version: use eval(string) to generalize test.
(One of the homework problems asks you to write a python
program to verify some syllogisms using truth tables.)
OK, so let's do a lewis carroll logic puzzle.
(1) Every one who is sane can do Logic;
(2) No lunatics are fit to serve on a jury;
(3) None of your sons can do Logic.
What conclusion can be drawn?
Use a = able to do Logic
b = fit to serve on a jury
c = sane
d = your sons
Express each line as a boolean expression.
Use the rules of boolean algebra to draw a short conclusion.
Then we have
c → a sane → does logic
not c → not b not sane → not fit to be on jury
d → not a your son → can't do logic
Using the above identities,
the first is eqivalent to ( (not a) → (not c) ).
Then stringing them all together gives
d → not a → not c → not b
which in English says
Your sons are not fit to serve on a jury.
Voila.
'if', 'while', and all that
So what does this do ?
for x in range(20):
if (x < 10) and (x > 5):
print "x is between 5 and 10"
else:
print "."
How about this ?
numbers = [1,2,10,20,50,80]
while numbers:
x = numbers.pop(0)
print x
"if" and "while" class exercise
TLDR : several new constructs including
# the IF statement !
if condition:
do_yes_case()
else:
do_no_case()
# the WHILE statement !
while condition:
do_stuff()
Very powerful stuff.
Your turn :
- Write a program that finds the smallest number that is divisible by 1 through 20.
- Approach?
- What loops are needed?
- What branches? Where?
The idea is:
- Write a function that returns True if x is divisible by some y.
- Use that along with a loop to write a function that returns True if x is divisible by 1 through n.
- Use that to try n, n+1, ... until we find a number divisible by 1 through n.
Time for your suggestions; I'll type.
(Don't look yet, but one answer is
here .)
tricky corners
Optional material for those who are strong in the force.
ternary "if ... else" form
Sometimes this form is called a "ternary operator" : ( ___ if ___ else ___ )
result = "yes" if 1 < 3 else "no" # a conditional on one line!
Several languages have constructs like this. In C it's written as ( ___ ? ___ : ___ )
where the first thing is the condition, i.e.
a = i > j ? i : j # This is C code. "a" is set to the bigger of i and j.
shortcut evaluation
The "___ or ___" and "___ and ___" operators behave in an interesting "shortcut"
fashion, evaluating the left argument first and then only evaluating
the right one if needed. Since "evaluation" can have side effects
(such as printing), this means that the "or", "and" operators
can also act as a kind of branching "if" statement.
Here's an example.
def foo(i, j):
print "Called foo({}, {})".format(i,j)
return i < j
# What do these four statements print? Explain
print "a: "
print foo(1, 3) or foo(3, 1)
print "b: "
print foo(3, 1) or foo(1, 3)
print "c: "
print foo(1, 3) and foo(3, 1)
print "d: "
print foo(3, 1) and foo(1, 3)
the boolean type
One more topic : what do you think of this function?
def true_if_three(x):
if x == 3:
return True
else:
return False
more practice