Take a look at the following Python function which on my machine lives in
def encode_long(x): r"""Encode a long to a two's complement little-endian binary string. Note that 0L is a special case, returning an empty string, to save a byte in the LONG1 pickling context. >>> encode_long(0L) '' >>> encode_long(255L) '\xff\x00' >>> encode_long(32767L) '\xff\x7f' >>> encode_long(-256L) '\x00\xff' >>> encode_long(-32768L) '\x00\x80' >>> encode_long(-128L) '\x80' >>> encode_long(127L) '\x7f' >>> """ ....
The triple quoted string which follows the function declaration is the
function's docstring (and the
r which prefixes the string makes this a raw
string, ensuring that the
\'s which follow are not used as escape
characters). This particular docstring provides a concise description of what
the function does, fleshed out with some examples of the function in action.
These examples exercise special cases and boundary cases, rather like a unit
>>> import pickle >>> import doctest >>> doctest.testmod(pickle) (0, 14)
The test result,
(0, 14), indicates 14 tests have run with 0 failures. For
more details try
doctest.testmod(pickle, verbose=True). In case anyone is
confused, 7 of the tests apply to
encode_long – and unsurprisingly the
other 7 apply to
pickle.py is executed (rather than imported as a library) it
runs these tests directly.
doctest module is a metaprogram – an example of Python being used to
both read and execute Python. To see how it works I suggest taking a
look at its implementation. The code runs to about 1500 lines of which the
majority are documentation and many of the rest are to do with providing
flexibility for more advanced use.
In essence, note that docstrings are not a comments, they are formal object
attributes. Now, Python allows you to list and categorise objects at runtime,
so we can collect up the docstrings for classes, class methods and for the
module itself. Once we have all these docstrings we can search them to find
anything which looks like the output of an interactive session using Python's
text parsing capabilities. The remaining twist is Python's ability to
dynamically compile and execute source code using the
commands. So, we can replay the documentation examples, capturing and checking
doctest module provides no more than an introduction to metaprogramming in
Python. Given a Python object it is possible to get at the object's class,
which is itself an object which can be dynamically queried and even modified
at run-time. This isn't the sort of trick which is often required: I haven't
tried it myself so I'd better keep quiet and refer you to the experts. See for
example van Rossum or Raymond.
|Copyright © 2005 Thomas Guest|