Syntax and Control Structures

Overview

The Python interpreter

Running programs

walsh:tmp joe$ echo "print 'Hi PyGotham'" > hello.py
walsh:tmp joe$ python hello.py 
Hi PyGotham

Interactive shell

>>> # prompts for an expression or statement
... # prompts that an expression or statement needs more input
5 + 3
import sys
if True:
	print "I don't believe it!"
if True: # waiting for input shows an error
...
# show what "asdf" vs "" resolves to in if statement

Some mild introspection... and others

help() # no params gives you interactive help.  "quit" or ^D to quit.
keywords, ^D
help([1, 2, 3]), import sys, help(sys) #... by the way, brackets denotes a list!
import sys, dir(sys), dir(""), dir([]) # import brings in a module... (which is just a file with code)
type(sys), type(5), li = [], type(li), dir(li), type(li.append),
 help(li.append), li, li.append('foo'), li

Syntax

Basic syntax

Dot notation, functions/methods and attributes

>>> class Foo:
...  def __init__(self):
...   self.bar = 12

Expressions and simple assignment

Space! Object spaces, namespaces

a = "A string"
b = ["a", "list", "of", "strings"]
"a " + "b " + "c"

Which looks like...

"""
namespace         object space
----------         -------------
a   ----------->   "A string"

b   ----------->   ["a", ...."strings"]

                   "a " + "b " + "c" ---> not referenced! 


"""

And that matters... why? (assignment binding)

Queue crude ASCII art

a = [1, 2, 3]
b = a
"""
a -------->[1, 2, 3]
             ^
b -----------|
"""


a = [1, 2, 3]
b = [1, 2, 3]
"""
a --->[1, 2, 3]
b --->[1, 2, 3]
"""

Control structures

Conditionals

>>> animal = "duck"
>>> if animal == "cat":
...  print "meow"
... elif animal == "duck":
...  print "quack"
... else:
...  print "are you sure it's not a mineral?"

Loops

>>> for i in [-1, 1, 1, 5]:
...  print i + 2
>>> for k, v in {'name':'doughnut', 
...  'flavor':'frosted with sprinkles'}.items():
...  print "key = " + k + ", value = " + v
>>> while(True):
...  print 'too.  many.  sprinkles.'

Loopier

>>> for i in range(5):
...  pass 
>>> for i in range(5):
...  print i
... else:
...  print "done"
(demo) Pass doesn't do anything at all (use for loop) (demo) break and continue if necessary

Loopiest

>>> {'foo':'bar', 'baz':'qux'}.items()
[('foo', 'bar'), ('baz', 'qux')]

>>> for a, b, c in [(1, 2, 3),(4, 5, 6),(7, 8, 9)]:
...  print str(a) + ", " + str(b) + ", " + str(c)
... 
1, 2, 3
4, 5, 6
7, 8, 9
(demo) mentioned items... what does that do? dictionary to list of tuples

Exceptions

>>> li = [1, 2]
>>> try:
...  print li[42]
... except Exception, e:
...  print 'Oh noez ' + str(e)
... 
Oh noez list index out of range
>>> raise Exception("Estoy enfermo")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Exception: Estoy enfermo
>>> 

Catching 'em all (multiple exception types)

>>> def raise_e(e):
...  try:
...   raise e
...  except (NameError, IndexError) as e:
...   print type(e)
... 
>>> raise_e(Exception)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in raise_e
Exception

A brief detour

FizzBuzz

Print integers 1 to 100, but replace multiples of 3 with "Fizz" and multiples of 5 with "Buzz" and multiples of both with "FizzBuzz"

joe@walsh~/projects/archived/fizzbuzz$ python fizzbuzz.py 
1
2
fizz
4
buzz
fizz
7
8
fizz
buzz
11
fizz
13
14
fizzbuzz
ACTIVITY TIME!

One way to do it:

for n in range(1,100):
	if n % 3 == 0 and n % 5 == 0:
		print "fizzbuzz"
	elif n % 3 == 0:
		print "fizz"
	elif n % 5 == 0:
		print "buzz"
	else:
		print n

Data types

Types of types (Yeah, really)

Accept Recreate the things you cannot change...

Some types in Python are not mutable, like strings and numbers! (Remember, values have types).

>>> a
'foo'
>>> b
'foo'
>>> a + " bar"
'foo bar'
>>> a
'foo'
>>> b
'foo'
>>> a = a + " bar"
>>> a
'foo bar'

A new string is actually being made when you do concatenation; you don't get a modified version of the old string.

Change the things you can (by reference)

Compare that to what happens with mutable data types like lists

>>> a = [1, 2, 3]
>>> b = a
>>> a
[1, 2, 3]
>>> b
[1, 2, 3]
>>> a.append(4)
>>> a
[1, 2, 3, 4]
>>> b # what will the value be?

Numbers

About sequences...

questions!
>>> "nerds"[0] #first element,  >>> "nerds"[4] #last element (n - 1)
>>> "nerds"[5] #IndexError 
>>> "nerds"[-1] #from the right,  >>> "nerds"[-2] #again
>>> "nerds"[0:2] #slices
>>> "nerds"[3:1] #nothing to slice
>>> "nerds"[3:-1] #something to slice even though negative
>>> "nerds"[3:] #no end index,  >>> "nerds"[:2] #no start index

Strings

String formatting / interpolation

>>> a = "milk"
>>> b = "cookies"
>>> s = "I like %s and %s" % (a, b)
>>> s
'I like milk and cookies'

% what?

Common string functions and methods

String methods and functions can be used on both variables and string literals:

a = "foo"
a.upper()
"foo".upper()

Common functions and methods:

len("foo") # length of string
re.sub("a.$", "ooooo", "foo bar baz") # regex
"  foo ".strip() # strip surrounding whitespace
"foo".startswith('f') # true if string starts with x
"foo".startswith('f') # true if string starts with x
"foo bar baz".split(' ') # returns list of substrings

Lists

List comprehensions

>>> [s.strip() for s in ['   space ', 'man   ']]
['space', 'man']
>>> [s.strip() for s in ['   space ', 'man   '] \
...  if s.upper().strip() == 'MAN']
['man']
map maps a function to every element in an array/list
filter filters an array/list using a function
lambda allows for anonymous functions
.... all of these actually exist in Python

Another look

>>> [s.strip() for s in ['   space ', 'man   '] \
...  if s.upper().strip() == 'MAN']
['man']

A few quick exercises

Use a for loop that will iterate over a list and create a new list with the cubes of every value in the first list. Use range to create the initial list.


Use a for loop to go through a list of names. Return a new list containing filtered list of three letter names all transformed to upper case The list of names is as follows: ['bob', 'alice', 'carol', 'dave', 'eve' ]


Do both exercises above using list comprehensions.

Solutions

>>>[x.upper() for x in ['bob', 'alice', 'carol', 'dave', 'eve' ] if len(x) == 3]
['BOB', 'EVE']
>>> [x**3 for x in range(5)]
[0, 1, 8, 27, 64]
>>> [x**3 for x in range(1,5)]
[1, 8, 27, 64]
>>> [x**3 for x in range(1,6)]

Common list functions

Tuples

(demo) can't append because immutable
(demo) just commas
(demo) packing unpacking
(demo) for k, v in ...

Dictionary

Iterating through dictionaries

>>> d = {'foo':'bar', 'baz':'qux'}
>>> for e in d:
...  print e
... 
foo
baz
?

There's a bit more to it

Booleans and comparison operators

7 >5 > 2 # chained
>>> 0 and 25 # left hand op is False and "and"
>>> 25 and 0
>>> 25 and 35
>>> 25 and 35 and 45
# note that these evaluate to True or False
(8 > 2) and "foo" or "bar" # trick for ternary, but don't do it...

What's considered False?


Everything else is True

Using modules

Putting it all together

Use urllib and json to get tweets about Python using the twitter search API:


You'll need a couple of bits of information:

ACTIVITY TIME

A bit of help

>>> import urllib
>>> import json
>>> # should probably look for IOError here...
>>> f = urllib.urlopen(\
...  'http://search.twitter.com/search.json?q=%40python')
...
>>> d = json.loads(f.read())
>>> d['results'][0]['text']