You are here: Home > Dive Into Python > The Power Of Introspection > Putting It All Together | << >> | ||||
Dive Into PythonPython from novice to pro |
The last line of code, the only one you haven't deconstructed yet, is the one that does all the work. But by now the work is easy, because everything you need is already set up just the way you need it. All the dominoes are in place; it's time to knock them down.
This is 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 that this is a list comprehension. As you know, methodList is a list of all the methods you care about in object. So you're looping through that list with method.
>>> 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 info function, object is the object you're getting help on, passed in as an argument. | |
As you're looping through methodList, method is the name of the current method. | |
Using the getattr function, you're getting a reference to the method function in the object module. | |
Now, printing the actual docstring of the method is easy. |
The next piece of the puzzle is the use of str around the docstring. As you may recall, str is a built-in function that coerces data into a string. But a docstring is always a string, so why bother with the str function? The answer is that not every function has a docstring, and if it doesn't, its __doc__ attribute is None.
>>> >>> def foo(): print 2 >>> >>> foo() 2 >>> >>> foo.__doc__ >>> foo.__doc__ == None True >>> str(foo.__doc__) '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 you are guaranteed to have a string, you can pass the string to processFunc, which you 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 you passed it None because None doesn't have a split method.
Stepping back even further, you see that you'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 you haven't seen before.
>>> s = 'buildConnectionString' >>> s.ljust(30) 'buildConnectionString ' >>> s.ljust(20) 'buildConnectionString'
You're almost finished. Given the padded method name from the ljust method and the (possibly collapsed) docstring from the call to processFunc, you concatenate the two and get a single string. Since you're mapping methodList, you end up with a list of strings. Using the join method of the string "\n", you join this list into a single string, with each element of the list on a separate line, and print the result.
That's the last piece of the puzzle. You should now understand this code.
print "\n".join(["%s %s" % (method.ljust(spacing), processFunc(str(getattr(object, method).__doc__))) for method in methodList])
<< Using lambda Functions |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
Summary >> |