cs253 »

Bridge the Gap Between CS101 and CS253

If you are taking CS253 as a followup to CS101 there are a few Python concepts that you will encounter that were not covered in CS101. Because CS253 is designed to teach web engineering and not necessarily Python basics, it can be frustrating trying to learn the web concepts without an understanding of the fundamental Python code that makes it happen.

This tutorial presents content and links to resources that will help to "bridge the gap" between CS101 and CS253.

Every good programmer knows how to learn on their own. Researching via google and the official documentation is vital. Asking good questions on the forums and in IRC channel cannot be underestimated as a learning tool. The basic information here will get you up and going (or at least point you in the right direction) and then encourage you to engage the Udacity community for the a more in-depth understanding.


Running Python on Your System

Udacity's Object Oriented Programming Class has a section on downloading and installing Python for Windows and Mac. If you are running Linux, you likely already have Python installed on your system. Otherwise, when Steve Huffman explains how to download and install Google App Engine, he also mentions how to download Python.

If you already have Python installed but are having trouble getting it to work properly with Google App Engine, reinstalling it following Steve's instructions might help. You may end up with two different versions of Python on your system, but that doesn't typically cause problems.

The inline help can be invaluable to quickly reference syntax. This will show the module's docstring. Type 'q' to quit the help.

>>> help(''.find)
Help on built-in function find:

    S.find(sub [,start [,end]]) -> int

    Return the lowest index in S where substring sub is found,
    such that sub is contained within s[start:end].  Optional
    arguments start and end are interpreted as in slice notation.

    Return -1 on failure.

You can exit the Python interpreter by typing 'quit()' or by using Ctrl + D

>>> quit()

Command Line Interpreter Resources

Object Oriented Programming (OOP) in Python

OOP is a huge topic. You don't need to be an OOP pro to build a blog in CS253, but understanding the basics can be very helpful. Google App Engine employs classes to create website handlers as subclasses of webapp2.RequestHandler object. (Sounds like gibberish? Don't worry, help is below.)

By far the most efficient way to learn OOP concepts and techniques is to take Udacity's Object Oriented Programming class. The class is designed to be completed relatively quickly. Even though it's not a prerequisite for cs253, going through it will give you a better handle on some of the material there. Also, at some point in your programming career you will encounter OOP, so the class might be a good way to acquire that knowledge base.

What if you're just not up for another class in addition to cs101 and cs253 right now? Fortunately there are some great tutorials on OOP in Python that will tell you everything you need to know.

Object Oriented Programming Resources


Tuples are a data structure like strings, lists and dicts. They can be thought of as "immutable lists". ('immutable' means 'you can't change it once you make it.' Unlike a list which you can change.) The syntax for creating a tuple is a comma separated list or a comma separated list inside of parentheses.

Here are some examples. To play along, type "Python" at a command line to bring up an interpreter, and then type the commands (the lines preceded by >>>) given below:

>>> my_list = ['Monty', "Python's", 'Flying', 'Circus']
>>> type(my_list)
<type 'list'>
>>> my_tuple = ('Monty', "Python's", 'Flying', 'Circus')
>>> type(my_tuple)
<type 'tuple'>
>>> my_list[0]
>>> my_tuple[0]
>>> my_list[0] = "spam" #lists are mutable
>>> my_list
['spam', "Python's", 'Flying', 'Circus']
>>> my_tuple[0] = "spam" #tuples are immutable
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> my_tuple
('Monty', "Python's", 'Flying', 'Circus')

Tuple Resources

Named Tuples

Named tuples are a quick, handy way to treat tuples as though they were objects (there's that word again). Say, for instance, that you have a collection of cars. Each car has a make, a model, and a year. You could have a straightforward list of tuples with that data:

cars = [('Honda', 'Accord', 2014), ('Ford', 'Explorer', 2011), ('Volkswagen', 'Jetta', 2012)]

But with named tuples, you could make the list more useful and easier to deal with. Named tuples are a part of the collections module, so you first need to do an import:

>>> from collections import namedtuple

Then you can define your Car object with its attributes. The following line of code defines a new data type named Car, along with three attributes make, model, and year:

>>> Car = namedtuple('Car', ['make', 'model', 'year'])

Now you can create as many objects of type Car as you like, by passing in the appropriate values:

>>> my_car = Car('Honda', 'Accord', 2014)
>>> sons_car = Car('Ford', 'Explorer', 2011)
>>> daughters_car = Car('Volkswagen', 'Jetta', 2012)

So if you want to check what kind of car your daughter drives, you can get very helpful output:

>>> daughters_car
Car('make'='Volkswagen', 'model'='Jetta', 'year'=2012)

By using object notation, you can get attributes as well:

>>> daughters_car.year

Of course this is a tuple still, so you can use indices if you prefer:

>>> daughters_car[2]

But as you'd expect with a tuple, unlike with regular objects, you can't set attributes:

>>> daughters_car.year = 2013
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

Named Tuple Resources

Regular Expressions

Regular Expressions are a powerful way to search strings for very specific patterns. Finding patterns in strings can be helpful when you want to do things like match a range of URLs or find out if a potential username contains any inappropriate characters. You don't need to know Regular Expressions in order to succeed in CS253. Steve gives you all of the Regular Expressions you'll need to use.

In Python Regular Expression are used by importing the re module.  Here is a simple regular expression: r'[0-9]+'. It matches one or more characters that can be any digit 0 through 9. For example:

>>> import re
>>> a = "A string with digits 1, 2, 3 and 4789"
>>> re.findall(r'[0-9]+', a)
['1', '2', '3', '4789']

Regular Expression Resources

List Comprehensions

List comprehensions are a powerful and efficient way to create loops that output a list. You don't need to know how to use list comprehensions to solve any of the problems presented in CS253, you may use a for or while loop and it will work just fine. However, Steve uses them in his code often and if you want to understand what his code is doing you should be familiar with how list comprehensions work.

Plus they are super awesome. Once you learn them you'll feel like the cool kid at a Jr. High lunch table.

>>> [x for x in range(3)]
[0, 1, 2]

Is pretty much an efficient way of saying:

>>> r = []
>>> for x in range(3):
...     r.append(x)
>>> r
[0, 1, 2]

Thankfully list comprehensions aren't too tricky and there are some great resources to learn about them.

List Comprehension Resources

Args and Kwargs

"star" * is Python syntax for "unpack this tuple (or list)" and "start star" ** is syntax for "unpack this dictionary". For example, let's say you have a function that takes 2 arguments 'x' and 'y'. If you pass in 2 arguments the function runs:

>>> def tuple_test(x, y):
...     x += 1
...     y += 1
...     return x, y
>>> tuple_test(1, 2)
(2, 3)

But if you try to pass a tuple in to the function you get an error:

>>> t = (1, 2)
>>> tuple_test(t)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: tuple_test() takes exactly 2 arguments (1 given)

This is because the tuple (1, 2) is treated as one argument. (The same way the list [1, 2] would be treated as a single argument.) In order to pass it into our function we need to "unpack" the tuple using *.

>>> tuple_test(*t)
(2, 3)

The same is true for a dictionary (Otherwise called "named arguments") which is unpacked with **:

>>> d = { 'x': 1, 'y': 2 }
>>> tuple_test(d)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: tt() takes exactly 2 arguments (1 given)
>>> tuple_test(**d)
(2, 3)

The values '1' and '2' get unpacked into the function which is expecting the arguments named 'x' and 'y', which are the keys in the dict.

Traditionally 'args' and 'kwargs' ('arguments' and 'keyword_arguments', or just 'a' and 'kw') are used together with * and **. Defining a function with *args, **kwargs allow you to have a variable number of arguments. Here the function foo() can take two, three or any number of arguments.

>>> def foo(*args, **kwargs):
...     return args if args else kwargs
>>> foo(1,2)
(1, 2)
>>> foo(1,2,3)
(1, 2, 3)
>>> foo(x=1, y=2)
{'x': 1, 'y': 2}

If this makes sense, you have it totally nailed:

>>> tuple_test(**foo(x=1, y=2))
(2, 3)
>>> tuple_test(*tuple_test(1,2))
(3, 4)

Args and Kwargs Resources

Modules or "How to Organize Your Code"

You can certainly complete CS253 by keeping all of your code in one huge main.py file. It'll become hard to manage and you'll spend a ton of time scrolling up and down, but it'll work. As an alternative you can modularize your code by moving it into different files in different directories and then importing into main.py. Modularization is also covered in Udacity's Object Oriented Programming class mentioned earlier.

Here's the absolute basics: 1. Create an empty file named __init__.py and place it in a directory. 2. You can now treat that directory like a module and import from it. 3. If this doesn't make sense, check out the resources.

Here's an example directory structure:



and here's a simplification of the code:

*** rot13.py ***
class rot13Handler(webapp2.RequestHandler):

*** main.py ***
from unit2.rot13 import rot13Handler

app = webapp2.WSGIApplication([('/', MainHandler),
                                ('/unit2/rot13', rot13Handler),
                                ], debug=True)

Modules Resources

Bonus: The Hidden Power of 'and' and 'or'

You were taught that and and or are used with booleans, which is true, but they are much more powerful than that. So, you can do stuff like this:

>>> True or False
>>> False or True
>>> True and True
>>> False or False

But did you know you could do stuff like this:

>>> 1 or 'one'
>>> 0 or 'zero'

Wait a moment now, what wizardry is this? Well, and and or are not simply boolean operators. They compare the "truthiness" or "falsiness" of an expression and return a value. If you pass them boolean values, (True or False) then they'll return booleans, but if you pass them some other type then they will return a value depending on its truthiness.

Empty iterators are considered falsey. So these values are treated like False:

0, None, '', [], {}, ()

This is how you can say:

def foo(a):
    if a:
        return "we got an a!"

Here foo will return "we got an a!" if a contains any non-empty value, otherwise it'll return None. Try it out: foo('') vs foo('some value')

So here is what or is really doing: 1. Takes in 2 parameters 2. Evaluates the "truthiness" of the first parameter 3. If True - return the first parameter (second parameter doesn't get evaluated) 4. If False - Evaluate and return the second parameter

>>> 1 or False
>>> 0 or False

Here is what and is really doing: 1. Takes in 2 parameters 2. Evaluates the "truthiness" of the first 3. If False - return the FIRST parameter 4. If True - evaluate and return the SECOND parameter

>>> 0 and False
>>> 1 and False

With this logic you can do some powerful things. You can give a variable a 'default' value:

b = a or "default"

If a holds a truthy value then b will be set to a, otherwise it'll be set to the string "default". Consider:

>>> a = ''
>>> b = a or "default"
>>> b
>>> a = 'now I have a value, haha!'
>>> b = a or "default"
>>> b
'now I have a value, haha!'

You can also use and and or together - somewhat like a ternary operator:

>>> def foo(a, b, c):
...     return a and b or c

If a has a truthy value, b is returned. If a has a falsey value, c is returned.

>>> a = ''
>>> b = 'bob'
>>> c = 'carol'
>>> foo(a, b, c)
>>> a = 'got a value now!'
>>> foo(a, b, c)

Warning: This relies on b having a Truthy value, if it doesn't you'll get unexpected results.

It's better practice to use if and else as they allow for falsey values in b and give more consistent results:

>>> b = a if a else 'default'
>>> def foo(a, b, c):
...     return b if a else c

Finally, note that not all Falsey values are equal. (but 0 and False are!)

>>> 0
>>> False
>>> ''
>>> None
>>> 0 == False
>>> 0 is False
>>> '' == False
>>> None == False

'and' and 'or' Reference