A Newb Learns Python

Python: For all your JSON pretty printing needs

Why use a website when Python can pretty print json right in your terminal…

>>> cat search.json
{"responseHeader":{"status":0,"QTime":0},"response":{"numFound":86295,"start":0,"docs":[{"artist":"Explosions in the Sky","id":"6-1010373","image":"67660114.jpg","reach":768165,"resid":1010373,"restype":6,"weight":1.0},{"artist":"Skid Row","id":"6-1000620","image":"796810.jpg","reach":515805,"resid":1000620,"restype":6,"weight":1.0}]}}

>>> cat search.json | python -m json.tool
{
    "response": {
        "docs": [
            {
                "artist": "Explosions in the Sky", 
                "id": "6-1010373", 
                "image": "67660114.jpg", 
                "reach": 768165, 
                "resid": 1010373, 
                "restype": 6, 
                "weight": 1.0
            }, 
            {
                "artist": "Skid Row", 
                "id": "6-1000620", 
                "image": "796810.jpg", 
                "reach": 515805, 
                "resid": 1000620, 
                "restype": 6, 
                "weight": 1.0
            }
        ], 
        "numFound": 86295, 
        "start": 0
    }, 
    "responseHeader": {
        "QTime": 0, 
        "status": 0
    }
}

Is the JSON already in your clipboard? No need to put it in a file, just use the builtin “pbpaste” command-line tool.

>>> pbpaste | python -m json.tool
{
    "cool": "this was something I just copied in my browser", 
    "pbpaste": "is a neat little utility"
}

(Source: richardlog.com)

Any and All Your Booleans Are Belong To Us

I wondered if there was a helper method for this…

>>> all([True, True])
True
>>> any([True, True])
True
>>> all([True, False])
False
>>> any([True, False])
True
>>> any([False, False])
False

What on earth did I name that variable?

Ever forget the name of that variable/class you defined in the interpreter? Just use locals().

>>> forgotten_variable = 17
>>> sarah_marshall = 0
>>> class Baz:
...     def __init__(self):
...             pass
>>> foo = Baz()
>>> 
>>> locals()
{'forgotten_variable': 17, '__builtins__': , 'Baz': , '__package__': None, '__name__': '__main__', 'foo': <__main__.Baz instance at 0x10bbdd8c0>, 'sarah_marshall': 0, '__doc__': None}
>>> 

When is isn’t

It’s important to note that == checks equality while “is” checks that they are the same object.

>>> class Buzz:
...     def __init__(self, a):
...             self.a = a
...     def __eq__(self, other):
...             return self.a == other.a
... 
>>> Buzz(3) == Buzz(3)
True
>>> Buzz(3) is Buzz(3)
False
>>> x = Buzz(3)
>>> y = Buzz(3)
>>> x == y
True
>>> x is y
False
>>> x is x
True

What does that method do again?

Just print the doc string…

>>> {}.fromkeys.__doc__
'dict.fromkeys(S[,v]) -> New dict with keys from S and values equal to v.\nv defaults to None.'
>>> {}.popitem.__doc__
'D.popitem() -> (k, v), remove and return some (key, value) pair as a\n2-tuple; but raise KeyError if D is empty.'
>>> 
>>> [].count.__doc__
'L.count(value) -> integer -- return number of occurrences of value'

Capping A List’s Length

Need to maintain a list of the last n objects you’ve seen? Stop writing that while loop over and over and use a deque!

>>> from collections import deque
>>> buffer = deque([],3)
>>> buffer.append("hello")
>>> buffer
deque(['hello'], maxlen=3)
>>> buffer.append("my")
>>> buffer
deque(['hello', 'my'], maxlen=3)
>>> buffer.append("name")
>>> buffer
deque(['hello', 'my', 'name'], maxlen=3)
>>> buffer.append("is")
>>> buffer
deque(['my', 'name', 'is'], maxlen=3)
>>> buffer.append("bob")
>>> buffer
deque(['name', 'is', 'bob'], maxlen=3)
>>> 

Tired of Summing Keys in Dictionaries?

I constantly find myself needing to tally up entries in lists. I always used to write this same pattern:

>>> winners = ["sally","sally","sally","bobby","bobby","jenny"]
>>> d = {}
>>> for w in winners:
...     d[w] = d.get(w, 0) + 1
>>> d
{'sally': 3, 'jenny': 1, 'bobby': 2}

Then along came the Counter in collections. Its nicer, cleaner, and more useful than the previous dictionary implementation. It also comes with handy methods like “most_common” which would take a bit of code to do with the above dictionary.

>>> from collections import Counter
>>> winners = ["sally","sally","sally","bobby","bobby","jenny"]
>>> c = Counter(winners)
>>> # How many times did bobby win?
>>> c["bobby"]
2
>>> # Who won the most?
>>> w.most_common(1)
[('sally', 3)]

The more a learn about collections the more I like them.

Tired of KeyErrors with Dictionaries?

It took me far to long to figure out how to nicely deal with keys that may not be in a dict. “get” and “in” are your friends.

>>> d = {"kittens" : 3, "dogs" : 0}
>>> d["kittens"]
3
>>> d["octopi"]
Traceback (most recent call last):
  File "", line 1, in 
KeyError: 'octopi'
>>> 
>>> d.get("kittens")
3
>>> d.get("octopi")
>>> 
>>> # provide a default value for when it isn't in the dict
... d.get("octopi",7)
7
>>> 
>>> "kittens" in d
True
>>> "octopi" in d
False
>>> 

Why You Don’t Use Objects as Default Parameters

Its so tempting to have a list or dict as a default argument for a method, don’t do it! The object is initialized only initialized once so it uses the same object over and over which probably isn’t what you want.

>>> import random
>>> def foo(input=[]):
...     input.append(random.random())
...     return input
... 
>>> foo()
[0.9352160354987816]
>>> foo()
[0.9352160354987816, 0.7154399343290632]
>>> foo()
[0.9352160354987816, 0.7154399343290632, 0.8816456865391322]

For more about this see: http://www.deadlybloodyserious.com/2008/05/default-argument-blunders/

Instead use this common pattern:

>>> import random
>>> def bar(input=None):
...     if input is None:
...             input = []
...     input.append(random.random())
...     return input
... 
>>> bar()
[0.573989616545463]
>>> bar()
[0.08395088701797537]
>>> bar()
[0.5669531424195319]
>>>