A quick digest below. Note that Python3 takes some of these features to the next level, so switching from 2 to 3 is a good idea :)
Use enumerate to loop over collections and indices, use reversed(collections) to loop backwards.
Use the zip built-in to loop over two collections: zip(collection1, collection2). To make a dict from two collections: dict(zip(names, colors)). Use zip_longest if the collections are not of the same length.
Use the sorted key argument to customize sort order of a collection, so to sort by dict value you can use: sorted(d.items(), key=lambda a: a)
Use iter() if you need to call a function until a sentinel value, see a good example here.
The for / else construct can be useful to know if a loop made it to the end (that is no break was hit).
Dicts: don't mutate a dictionary when looping over it! In Python3 dictionaries have view objects: "The objects returned by dict.keys(), dict.values() and dict.items() are view objects. They provide a dynamic view on the dictionary’s entries, which means that when the dictionary changes, the view reflects these changes.". For Python2 use iteritems() which returns an iterator (faster).
Use collections.defaultdict to prevent initializing keys manually.
Use ChainMap to link (concatenate) dictionaries together.
Keyword arguments can make a function more readable, same goes for the light-weight namedtuple (collections module).
Unpacking: bob, julian = 'bob julian'.split(), or a variable swap is as easy as a, b = b, a (no temp variable).
Use ''.join(collection) instread of concatenating a string in a loop (more efficient).
Use deque if you need a stack / queue ('linked list') instead of a regular list ('array'). When you do somecollection.insert(0, 'value'), it is time to change to a deque structure and use somecollection.appendleft('value').
Use decorators to factor-out administrative logic, for example @cache, @timeit, etc. (use functools.lru_cache for caching starting 3.2).
Use the with statement (context manager) to open and (automatically) close files. Another use case is threading locks or more generically when you need to factor-out "temporary contexts".
Generator expressions are faster, you can use them (instead of list comprehensions) in sum() / max() / min() to gain performance. Hard to beat this for compactness: sum(i**2 for i in range(10))
Do you want to get 250+ concise and applicable Python tips in an ebook that will cost you less than 10 bucks (future updates included), check it out here.
"The discussions are succinct yet thorough enough to give you a solid grasp of the particular problem. I just wish I would have had this book when I started learning Python." - Daniel H
"Bob and Julian are the masters at aggregating these small snippets of code that can really make certain aspects of coding easier." - Jesse B
"This is now my favourite first Python go-to reference." - Anthony L
"Do you ever go on one of those cooking websites for a recipe and have to scroll for what feels like an eternity to get to the ingredients and the 4 steps the recipe actually takes? This is the opposite of that." - Sergio S