We'll measure Python with two yardsticks. First, we'll look at a
yardstick originally used for Java. Then we'll look at yardstick based on
experience designing Modula-2.
The Java Language Environment White
Paper [Gosling96] lists a number of
desirable features of a programming language:
- Simple and Familiar
- Object-Oriented
- Secure
- Interpreted
- Dynamic
- Architecture Neutral
- Portable
- Robust
- Multithreaded
- Garbage Collection
- Exceptions
- High Performance
Python meets and exceeds most of these expectations. We'll look
closely at each of these twelve desireable attributes.
Simple and Familiar. By simple, we mean that there is no GOTO statement, we don't
need to explicitly manage memory and pointers, there is no confusing
preprocessor, we don't have the aliasing problems associated wuth
unions. We note that this list summarizes the most confusing and
bug-inducing features of the C programming language.
Python is simple. It relies on a few core data structures and
statements. The rich set of features is introduced by explicit import of
extension modules. Python lacks the problem-plagued GOTO statement, and
includes the more reliable
break
,
continue
and exception
raise
statements. Python conceals the mechanics of object references from the
programmer, making it impossible to corrupt a pointer. There is no
language preprocessor to obscure the syntax of the language. There is no
C-style union (or COBOL-style REDEFINES) to create problematic aliases
for data in memory.
Python uses an English-like syntax, making it reasonably familiar
to people who read and write English or related languages. There are few
syntax rules, and ordinary, obvious indentation is used to make the
structure of the software very clear.
Object-Oriented. Python is object oriented. Almost all language features are
first class objects, and can be used in a variety of contexts. This is
distinct from Java and C++ which create confusion by having objects as
well as primitive data types that are not objects. The built-in
type
(
x
) function
can interrogate the types of all objects. The language permits
creation of new object classes. It supports single and multiple
inheritance. Polymorphism is supported via run-time interpretation,
leading to some additional implementation freedoms not permitted in
Java or C++.
Secure. The Python language environment is reasonably secure from
tampering. Pre-compiled python modules can be distributed to prevent
altering the source code. Additional security checks can be added by
supplementing the built-in __import__
function.
Many security flaws are problems with operating systems or
framework software (for example, database servers or web servers). There
is, however, one prominent language-related security problem: the
"buffer overflow" problem, where an input buffer, of finite size, is
overwritten by input data which is larger than the available buffer.
Python doesn't suffer from this problem.
Python is a dynamic language, and abuse of features like the
exec
statement or the eval
function can introduce security problems. These mechanisms are easy to
identify and audit in a large program.
Interpreted. An interpreted language, like Python allows for rapid, flexible,
exploratory software development. Compiled languages require a
sometimes lengthy edit-compile-link-execute cycle. Interpreted
languages permit a simpler edit-execute cycle. Interpreted languages
can support a complete debugging and diagnostic environment. The
Python interpreter can be run interactively; which can help with
program development and testing.
The Python interpreter can be extended with additional
high-performance modules. Also, the Python interpreter can be embedded
into another application to provide a handy scripting extension to that
application.
Dynamic. Python executes dynamically. Python modules can be distributed
as source; they are compiled (if necessary) at import time. Object
messages are interpreted, and problems are reported at run time,
allowing for flexible development of applications.
In C++, any change to centrally used class headers will lead to
lengthy recompilation of dependent modules. In Java, a change to the
public interface of a class can invalidate a number of other modules,
leading to recompilation in the best case, or runtime errors in the
worst case.
Portable. Since Python rests squarely on a portable C source, Python
programs behave the same on a variety of platforms. Subtle issues like
memory management are completely hidden. Operating system
inconsistency makes it impossible to provide perfect portability of
every feature. Portable GUI's are built using the widely-ported Tk GUI
tools Tkinter
, or the GTK+ tools and the the
pyGTK
bindings.
Robust. Programmers do not directly manipulate memory or pointers,
making the language run-time environment very robust. Errors are
raised as exceptions, allowing programs to catch and handle a variety
of conditions. All Python language mistakes lead to simple,
easy-to-interpret error messages from exceptions.
Multithreaded. The Python threading
module is a
Posix-compliant threading library. This is not completely supported on
all platforms, but does provide the necessary interfaces. Beyond
thread management, OS process management is also available, as are
execution of shell scripts and other programs from within a Python
program.
Additionally, many of the web frameworks include thread
management. In products like TurboGears, individual web requests
implicitly spawn new threads.
Garbage Collection. Memory-management can be done with explicit deletes or automated
garbage collection. Since Python uses garbage collection, the
programmer doesn't have to worry about memory leaks (failure to
delete) or dangling references (deleting too early).
The Python run-time environment handles garbage collection of all
Python objects. Reference counters are used to assure that no live
objects are removed. When objects go out of scope, they are eligible for
garbage collection.
Exceptions. Python has exceptions, and a sophisticated
try
statement that handles exceptions. Unlike the
standard C library where status codes are returned from some
functions, invalid pointers returned from others and a global error
number variable used for determining error conditions, Python signals
almost all errors with an exception. Even common, generic OS services
are wrapped so that exceptions are raised in a
uniform way.
High Performance. The Python interpreter is quite fast. However, where necessary,
a class or module that is a bottleneck can be rewritten in C or C++,
creating an extension to the runtime environment that improves
performance.
One of the languages which strongly influenced the design of
Python was Modula-2. In 1974, N. Wirth (creator of Pascal and its
successor, Modula-2) wrote an article “On
the Design of Programming Languages”
[Wirth74], which defined some other considerations in
designing a programming language. He suggests the following:
-
a language be easy to learn and easy to use;
-
safe from misinterpretation;
-
extensible without changing existing features;
-
machine [
platform
] independent;
-
the compiler [
interpreter
] must be fast
and compact;
-
there must be ready access to system services, libraries and
extensions written in other languages;
-
the whole package must be portable.
Python syntax is designed for readability; the language is quite
simple, making it easy to learn and use. The Python community is always
alert to ways to simplify Python. The Python 3000 project is actively
working to remove a few poorly-concieved features of Python. This will
mean that Python 3.0 will be simpler and easier to use, but incompatible
with Python 2.x in a few areas.
Most Python features are brought in via modules, assuring that
extensions do not change or break existing features. This allows
tremendous flexibility and permits rapid growth in the language
libraries.
The Python interpreter is very small. Typically, it is smaller
than the Java Virtual Machine. Since Python is (ultimately) written in
C, it has the same kind of broad access to external libraries and
extensions. Also, this makes Python completely portable.