Python Update

Andrew Kuchling

Issue #37, May 1997

Python has evolved since we last had an article on it. Andrew Kuchling brings us up to date in this article, and we invite readers to submit suggestions for Python topics Andrew might cover in future issues of Linux Journal.

What's been happening to Python since J. Bauer's article in Linux Journal #35? Like most free software, Python is being continually developed and enhanced. At the time of the original article, Python was at version number 1.2, and betas of 1.3 were floating around. Since then, version 1.3 has been officially released, only to be replaced by 1.4 in late October.

Versions 1.3 and 1.4 have both added new features to the language. The really significant new item in 1.3 was the addition of keyword arguments to functions, similar to Modula-3's. For example, if we have the function definition:

def curse(subject="seven large chickens",
          verb="redecorate",
          object="rumpus room"):
    print "May", subject, verb, "your", object

then the following calls are all legal:

curse()
curse('a spaniel', 'pour yogurt on', 'hamburger')
curse(object='garage')
curse('the silent majority', object='Honda')
Arguments not preceded by a keyword are passed in the usual fashion; non-keyword and keyword arguments can be used in the same function call, as long as the non-keyword parameters precede the keyword parameters. By that rule, the following call is a syntax error:
curse(object='psychoanalyst', 'a ancient philosopher')
and the following call would cause an error at runtime, because an argument is being defined twice:
curse('the silent majority', subject='Honda')
As a pleasant side effect, adding keyword arguments required optimising function calls, reducing the overhead of a single function call by roughly 20%.

Most of the changes in the 1.4 release made Python more useful for numeric tasks. Many of the changes were proposed by the members of the Matrix special interest group (or Matrix-SIG), which has defined a syntax and built a data type for manipulating matrices. (The Python SIGs are small groups of people tightly focused on one application of Python, such as numeric programming or database interfaces; see http://www.python.org/sigs/ for more information about the existing SIGs.)

One such enhancement is support for complex numbers. The imaginary component of a complex number is denoted by a suffix of “J” or “j”; thus, the square root of -1 is symbolized as 1j . The usual mathematical operations such as addition and multiplication can be performed on complex numbers, of course.

>>> 1+2j*2
(1+4j)
>>> (1+2j)*2
(2+4j)
>>> (1+2j)/(2+1j)
(0.8+0.6j)

The presence of complex numbers also requires mathematical functions that can perform operations on them. Instead of updating the existing math module, a new module called cmath was added; old software might malfunction if an operation returns a complex value where an error was expected. So math.sqrt(-1) will always raise a ValueError exception, while cmath.sqrt(-1) will return a complex result of 1j.

>>> import cmath
>>> cmath.sqrt(-1)
1j
>>> a=cmath.log(1+2j)
>>> print a
(0.804718956217+1.10714871779j)
>>> cmath.exp(a)
(1+2j)
For the sake of users comfortable with Fortran's notation, the ** operator has been added for computing powers; it's simply a shorthand for Python's existing pow() function. For example, 10**2 is equivalent to pow(10,2) and returns 100.

One minor new function has been requested by several people in comp.lang.python. Python has long had a tuple() function which converts a sequence type (like a string or a list) into a tuple; the usual idiom for converting sequence types to lists was map(None, L). (The function map(F,S) returns a list containing the result of function F, performed on each of the elements of the sequence S. If F is None, as in this case, then no operation is performed on the elements, beyond placing them in a list.)

Many people found this asymmetry—tuple() existed, but not list()—annoying. In 1.4, the list() function was added, which is symmetric to tuple().

>>> tuple([1,2,3])
(1, 2, 3)
>>> list( (1,2,3,4) )
[1, 2, 3, 4]

An experimental feature was included in 1.4 and caused quite a bit of controversy: private data belonging to an instance of a class is a little more private. An example will help to explain the effect of the change. Consider the following class:

class A:
    def __init__(self):
        self.__value=0
    def get(self): return self.__value
    def set(self, newval): self.__value=newval
Python doesn't support private data in classes, except by convention. The usual convention is private variables have names that start with at least one underscore. However, users of a class can disregard this and access the private value anyway. For example:
>>> instance=A()
>>> dir(instance)  # List all the attributes of the instance
['__value']
>>> instance.get()
0
>>> instance.__value=5
>>> instance.get()
5
A more significant problem; let's say you know nothing about A's implementation and try to create a subclass of A which adds a new method that uses a private __value attribute of its own. The two uses of the name will collide. Things are slightly different in 1.4:
>>> instance=A()
>>> dir(instance)
['_A__value']
Where did this new value come from? In 1.4, any attribute that begins with two underscores is changed to have _ and the class name prefixed to it. Let's say you have a class called File, and one method refers to a private variable called __mode the name will be changed to _File__mode.
>>> instance.get()
0
>>> instance.__value=5
>>> instance.get()
0
>>> dir(instance)
['_A__value', '__value']
Now, this still doesn't provide ironclad data hiding; callers can just refer explicitly to _A__value. However, subclasses of A can no longer accidentally stomp on private variables belonging to A.

This feature is still controversial and caused much debate in comp.lang.python when it was introduced. Thus, its status is only experimental, and it might be removed in a future version of the language, so it would be unwise to rely on it.

Both the 1.3 and 1.4 releases included some new modules as part of the Python library, and bug fixes and revisions to existing modules in the library. Most of these changes are only of interest to people who've written code for earlier versions of those modules; see the file Misc/NEWS in the Python source distribution for all the details. If you're just coming to the language, these changes aren't really of interest to you.

The news isn't just limited to the software. The first two books on Python were published in October: Programming Python, by Mark Lutz, Internet Programming with Python, by Aaron Watters, Guido van Rossum, and James C. Ahlstrom. At least one more book is scheduled for release next year.

Two Python workshops have taken place, one at the Lawrence Livermore National Labs in California last May, and another in Washington, D.C. in November. Speakers discussed all sorts of topics: distributed objects; interfacing C++ and Python, or Fortran and Python; and Web programming. See http://www.python.org/workshops/ for more information about the workshops and the papers presented.

In November 1996, the 5th Python Workshop was held, in association with the FedUnix '96 trade show. The two most common topics were numeric programming and Web-related programming. For numeric work, there's a lot of interest in using Python as a glue language to control mathematical function libraries written in Fortran or C++. Code can be developed quickly in Python, and once the program logic is correct it can be ported to a compiled language for speed's sake. There's also a benefit from using a general programming language like Python, instead of a specialized mathematical language; it's easier to make the numeric code accessible with a GUI written in Tk, or with a CGI interface.

Another popular topic was Web-related programming. The Python Object Publisher was an especially interesting system, which enables accessing Python objects via HTTP. To take an example from the Object Publisher presentation, a URL like:

http://www.here.com/Car/Pinto/purchase?name=Bob

causes a Python Car object named Pinto to be located, and its purchase() method will be called with 'Bob' as a parameter. Other presentations discussed generating HTML, writing tools for system administration, and collaborative document processing. Brief notes on the papers are at http://www.python.org/workshops/1996-11/, with links to HTML or PostScript versions.

As you read this, plans for the next workshop are probably in progress, though there's no news at the time of writing; see the Python Web site for the current status. In the past, the meetings have alternated between the Eastern and Western U.S., so workshop #6 will probably be on the West Coast.

References