# Dive Into Python Python for experienced programmers | Find:

## 2.8. Putting it all together

The last line of code, the only one we haven’t deconstructed yet, is the one that does all the work. But by now the work is easy, because everything we need is already set up just the way we need it. All the dominoes are in place; it’s time to knock them down.

### Example 2.25. The meat of `apihelper.py`

        print "\n".join(["%s %s" %
                          (method.ljust(spacing),
                           processFunc(str(getattr(object, method).__doc__)))
                         for method in methodList])

Note that this is one command, split over multiple lines, but it doesn’t use the line continuation character (“`\`”). Remember when I said that some expressions can be split into multiple lines without using a backslash? A list comprehension is one of those expressions, since the entire expression is contained in square brackets.

Now, let’s take it from the end and work backwards. The

    for method in methodList

shows us that this is a list comprehension. As you know, `methodList` is a list of all the methods we care about in `object`. So we’re looping through that list with `method`.

### Example 2.26. Getting a `doc string` dynamically

    >>> import odbchelper
    >>> object = odbchelper
    >>> method = 'buildConnectionString'
    >>> getattr(object, method)
    <function buildConnectionString at 010D6D74>
    >>> print getattr(object, method).__doc__
    Build a connection string from a dictionary of parameters.

        Returns string.

| In the `help` function, `object` is the object we’re getting help on, passed in as an argument.
| As we’re looping through `methodList`, `method` is the name of the current method.
| Using the `getattr` function, we’re getting a reference to the `method` function in the `object` module.
| Now, printing the actual `doc string` of the method is easy.

The next piece of the puzzle is the use of `str` around the `doc string`. As you may recall, `str` is a built-in function that coerces data into a string. But a `doc string` is always a string, so why bother with the `str` function? The answer is that not every function has a `doc string`, and if it doesn’t, its `__doc__` attribute is `None`.

### Example 2.27. Why use `str` on a `doc string`?

    >>> >>> def foo(): print 2
    >>> >>> foo()
    2
    >>> >>> foo.__doc__
    >>> foo.__doc__ == None
    1
    >>> str(foo.__doc__)
    'None'

| We can easily define a function that has no `doc string`, so its `__doc__` attribute is `None`. Confusingly, if you evaluate the `__doc__` attribute directly, the Python IDE prints nothing at all, which makes sense if you think about it, but is still unhelpful.
| You can verify that the value of the `__doc__` attribute is actually `None` by comparing it directly.
| Using the `str` function takes the null value and returns a string representation of it, `'None'`.

In SQL, you must use `IS NULL` instead of `= NULL` to compare a null value. In Python, you can use either `== None` or `is None`, but `is None` is faster.

Now that we are guaranteed to have a string, we can pass the string to `processFunc`, which we have already defined as a function that either does or doesn’t collapse whitespace. Now you see why it was important to use `str` to convert a `None` value into a string representation. `processFunc` is assuming a string argument and calling its `split` method, which would crash if we passed it `None` because `None` doesn’t have a `split` method.

Stepping back even further, we see that we’re using string formatting again to concatenate the return value of `processFunc` with the return value of `method`’s `ljust` method. This is a new string method that we haven’t seen before.

### Example 2.28. Introducing the `ljust` method

    >>> s = 'buildConnectionString'
    >>> s.ljust(30)
    'buildConnectionString         '
    >>> s.ljust(20)
    'buildConnectionString'

| `ljust` pads the string with spaces to the given length. This is what the `help` function uses to make two columns of output and line up all the `doc string`s in the second column.
| If the given length is smaller than the length of the string, `ljust` will simply return the string unchanged. It never truncates the string.

We’re almost done. Given the padded method name from the `ljust` method and the (possibly collapsed) `doc string` from the call to `processFunc`, we concatenate the two and get a single string. Since we’re mapping `methodList`, we end up with a list of strings. Using the `join` method of the string `"\n"`, we join this list into a single string, with each element of the list on a separate line, and print the result.

### Example 2.29. Printing a list

    >>> li = ['a', 'b', 'c']
    >>> print "\n".join(li)
    a
    b
    c

| This is also a useful debugging trick when you’re working with lists. And in Python, you’re always working with lists.

That’s the last piece of the puzzle. This code should now make perfect sense.

### Example 2.30. The meat of `apihelper.py`, revisited

        print "\n".join(["%s %s" %
                          (method.ljust(spacing),
                           processFunc(str(getattr(object, method).__doc__)))
                         for method in methodList])