Hot on the heels of my Comdex/Chicago session, at which Python architect Guido van Rossum spoke, version 2.1 of Python shipped, as did Programming Python, 2nd Edition, by Mark Lutz . Of course, Programming Python, 2nd Edition doesn’t cover Python 2.1, only Python 2.0, but that’s life in book publishing when the book’s subject progresses on Internet time.
I have to say that I’m fascinated by the evolution of this language. Guido and his team are managing to serve a variety of constituencies without introducing incompatibilities.
For instance, as described in the What’s New document, Python 2.1 adds support for the following:
PEP 227: Nested Scopes PEP 236: __Future__ Directives PEP 207: Rich Comparisons PEP 230: Warning Framework PEP 229: New Build System PEP 205: Weak References PEP 232: Function Attributes PEP 235: Case-Insensitive Platforms and Import PEP 217: Interactive Display Hook PEP 208: New Coercion Model PEP 241: Metadata in Python Packages
In the list above, the PEP numbers refer to Python Enhancement Proposals, Python’s community process for evolving the language. Python 2.1 is the first release that was steered by the PEP process. PEP appears to be a good thing, although no one could mistake it for a democratic process: Guido still pretty much decides what makes it into the language and what doesn’t.
That isn’t a criticism, by the way; every emerging programming language needs a Czar to keep it coherent. ANSI/ISO committees are more useful later in the language’s life cycle, some would say much later.
Nested Scopes, Future Directives, And Warnings Three enhancements, PEPs 227, 230, and 236 need to be discussed together. Python’s design has historically made functional programming in the language rather awkward. I use the term functional programming here in the specific sense expressed in the comp.lang.functional FAQ: “Functional programming is a style of programming that emphasizes the evaluation of expressions, rather than execution of commands.”
For instance, Scheme is considered to be a functional language, as are Haskell and ML; C++ is considered an imperative language. That isn’t to say that you can’t do functional programming in C++, or that you can’t do imperative programming in Scheme. As we old-timers say, you can write Fortran in any language.
The point here is that, up until now, Python only had three namespaces in which to resolve names: the local, global, and built-in namespaces. Functional programming makes heavy use of lambda expressions and nested functions, and those really require inner functions to be able to see the local variables of outer functions, and that feature is what has been added.
You may be wondering about lambda expressions. The idea and the term go all the way back to Lisp. In Python, the lambda expression yields an unnamed function that evaluates a single expression, and is often used for callback functions. Getting back to nested scopes: because adding nested scopes will break some existing code, Python 2.1 does not activate the feature by default. To write code that uses nested scopes, you need to activate it explicitly with a __future__ directive: from __future__ import nested_scopes.
In Python 2.2, nested scopes will be the default behavior. To warn people who have code that may break in the future, the current compiler also has a new warning framework (useful for other things as well), and will issue warnings for code that is incompatible with the new behavior. When the new behavior is turned on, the warnings become full syntax errors.
Anyway, with the new behavior, Python becomes a dandy functional programming language. It already had first-class functions, an exec statement, and an eval() function; the addition of nested scoping gives it some of the flavor of Algol or Scheme.