This file is a collection of things that are good to know about Python 3.
Conventions for the file:
   Keep the width less than 80 characters. 
   Let your text editor wrap text lines, if you want, but use a '\' to add
   line breaks to code segments that would otherwise wrap.
   
I hope this will be helpful.

Contributors: [chandera]


======Iterating over lists======

Say we had a list 
    
    li = [1, 2, 3, 4, 5]

An okay way to print all the items:

    i = 0
    while i < len(li):
        print(li[i])
        i+=1

A slightly better way to print all the items:

    for i in range(len(li)): #or, if you want to be explicit, range(0,5)
        print(li[i])
    
The best way (not actually) to print (access in some way) all the items in
li:
    
    for num in li:
        print(num)

If you wanted to do something with those values, that would be great. If
you just wanted to print them, you could write this instead:

    print('\n'.join(li))

This joins string versions of everything in the list with a newline
character, giving us '1\n2\n3\n4\n5' (the print statement adds its own
\n).

Of course, if you had some nested lists, you could foreach over each list:

    for innerlist in outerlist:
        for item in innerlist:
            pass

As you can see, Python's for loop is quite powerful. All of the built in
sequence types have __iter__() methods and will yield iterators (I
think). Use them. Love them.  

======Two dimensional arrays======

List comprehensions:
    Using a list comprehension, you can bulid a new list off some other 
    collection.

    Say you had a dictionary:

       dic = {1:2, 2:3, 3:4, 4:5}

    and you wanted to turn it into a list of keys * values. You could do
    this:

        li = []
        for k in d:
            li.append(k*dic[k])

    A list comprehension would be better! (In some cases, they are also
    better than map())

        li = [k*v for k, v in dic.items()]
    
    Isn't that nice? We can also generalize it to...nothing.

    Here's a function that returns a list full of None (or something else):

    def emptylist(n, item=None):
        return [item for x in range(n)]

    Note that if you provide one item, the list will be full of references 
    to it. 

    I haven't tested this code, but if you wanted nested empty lists:

    empty2d = emptylist(100, emptylist(100))

    If you were feeling really adventurous, you might write something like
    this:

    def superDuperHyperCubeBuilder(side, dimension):
        if dimension == 0:
            return None
        return [superDuperHyperCubeBuilder(side, dimension-1) for \
        x in side]

    You can access composed lists the way you would multidimensional arrays.
