Python, is such a general purpose language. Still, we must ask ourselves if Python brings anything special to the table. It is certainly true that it is a general purpose and like most modern languages it has adopted most of the popular programming metaphors which have developed in the past decade. Also in common with the more modern languages Python jettisons some of the older features which have outlived their usefulness. This though is not sufficient reason to go to the significant effort of acquiring a new language. So the question becomes, what does Python offer we can't find elsewhere.
Object Oriented - Python is completely object oriented. It comes with a full set of OO features borrowed from any environment which was looking the other way at the time. These include: A First Class Object Model with First Class functions. Multiple Inheritance. Classes, modules, exceptions and late (run-time) binding.
open layout - Python code is less cluttered with the syntactic noise of declarations and scope definitions. Scope in a Python program is defined by the indentation of the code in question. Python thus breaks with a major modern language tradition in that white space has now once again acquired significance.
automatic memory management - like Java, Python offers automated memory management through run-time reference counting and garbage collection of unreferenced objects.
embeddable - Python can be embedded in other products and programs as a control language. Python is attractive from the technical viewpoint as the interface to do this has been well exposed and is reasonably minimalist in nature and from the practical viewpoint because the Python License is truly public domain rather copyleft, copyright or copy-somewhere-in-the-middle. Python can be incorporated in anything without fear or difficulty.
extendable - Python can dynamically load, compiled Python, Python source, or even dynamically load new machine (object) code to provide new features and new facilities.
low-level access to interpreter - Python exposes its internal plumbing to a degree to allow programs to make use of the way the plumbing works.
rich external services - Python has a feature rich set of external services available. For example, network services, a GUI API (based on tcl/Tk) Web support for both the generation of HTML and the CGI interface, direct access to databases and so on.
The core of the Python language is the same ALGOL inspired procedural syntax and expression formation that has featured in most languages since then. Block structure as has been mentioned, is defined by the indentation of the source code which makes Python programs look quite unlike most other modern languages when first seen. The style of these indents is not significant as any white space is accepted, only equal amounts are counted off to determine equal block scope.
Python features many data structures not seen in more traditional computer languages. Some of these are familiar to us from awk and perl like associative arrays (hash tables to the traditionalists) called Dictionaries in Python and Lists, which are simply ordered array-like objects. Where Python differs from awk and perl is in the manipulation of these objects which in the OO style are done through intrinsic functions, which is Python nomenclature object defined access methods. Like Java, packaging the access and manipulation functions with the objects they access and manipulate makes namespace management easier, and allows greater clarity in the code you write.
Ranges (i.e. lists or virtual lists of integers) are also featured in our list of unique Python types. Python also has a number of composites of various sorts which can be treated as types as classes as structures are in other languages. Examples here are the Traceback, the Module and the File. This latter is the hook by the C standard I/O functions have been re-cast in Python.
Lets look at some code to give you the flavor of what we're talking about.
class Person: def __init__(self, name = '', job = '', pay = 0): self.name = name self.job = job self.pay = pay def __getattr__(self, name): if name =='tax': return self.pay * .30 else: raise AttributeError def __repr__(self): return 'Person |%s|' % self.name def info(self): return self.name, self.job, self.pay, self.taxHere is a reasonably simple code fragment which serves to illustrate what some Python code looks like. Note the lack of delimiters for the block structure. This is all OK until we get to the end of a block where Python has a slightly 'dangly & unfinished' feel when you first see it. The feeling passes, for what its worth.
Its also worth noting that the function names which start and end with double '_' characters are all overriding builtin (inherited) functions of the same names provided by Python itself. The __repr__ function provides a human readable representation of a Python object. This is analogous to the toString() functionality of Java. The __getattr__ function is used whenever a member variable is accessed in Python. In this case, we are trapping accesses to a member called 'tax' which you will note we have not defined, which allows us to access self.tax for instance at the end as if it was any other member variable while not needing real storage for it.
The example here, shows a both the syntax and a little bit of the Python philosophy. The overriding of inherited abilities as shown above is a simple and elegant mechanism for providing basic functions to the programmer. Nevertheless, it may not be to your taste.
Another feature worthy of mention is one which is more familiar to programmers who have worked with OO languages before. In Python these are the intrinsic functions (methods in most other OO languages). These functions allow the user to perform operations on the object for which they are defined. In the case of lists for example some of the following operations are common.
L = range(5) create a list L.append(-3) add an element to the end of the list L.insert(3, 50) insert an element at index 3 L.sort() sort the list del L[4:5] delete a slice (section) of list L.reverse() reverse the listThe benefits of this quickly become apparent after only a short period of use. The operations which are bound to an object are all reasonably clear (although inheritance often means that you can do more things to an object than you expected) and the type checking is less of an issue as the operations are bound to the type intrinsically. Its also true that strings of characters share some of characteristics of lists and to a limited extent can be manipulated in the same manner. (It must be noted that strings are more immutable than their 'C' counterparts but have much in common with the Java String class).
Another concept recently return to favor is that of exceptions. Python has exceptions and they look and behave much like the exceptions of C++ and Java (and soon to be C). The basic format is shown below:
raise SpamError how to raise an exceptionhandling the errors is then done in the following manner.
try: ... a bunch of statements ... except error, details: ... exception handling statements ... else: ... no exception raised ...Note that Python also supports a 'finally' clause as a catchall for code that must run whether an exception or non-exception exit is being followed.
Most of the rest of the language is unremarkable. The usual control constructs are all available albeit with a slightly new look about them. Expression evaluation is also a little more relaxed than it is in some other languages.
a = b = c = 0 multiple assignments [a, b] = ['a', 'b'] multiple different assignments w < x < y < z multiple range testingFinally, a quick word on the builtin functions which Python makes available. These are for the most part not worth dwelling on in detail. Each of the references had ample documentation on each of these functions. Here we merely list them to give a flavor of the facilities.
abs execfile locals reload apply filter long repr callable float map round chr getattr max setattr cmp globals min str coerce hasattr oct tuple compile hash open type delattr hex ord vars dir id pow xrange divmod input range eval int raw_input exec len reduce
Some of these libraries are crucial to the flexibility which Python offers the programmer. In fact, much of Python's appeal may lie in not in the any esoteric features of the language, but rather, the fact that so much work has already been done by others and made available for us to build on. So, lets look at what some of the libraries are:
from Tkinter import * win = Frame() win.pack() Label(win, text='Hello World').pack(side=TOP) Button(win, text='Quit', command=win.quit).pack(side=BOTTOM) win.mainloop()The code fragment above produces the output shown at the right. This is of course a laudably terse example of the "Hello World" but will not be setting the world on fire any time soon.
For those seeking an alternative, Python also offers the C STDWIN package which has been around for some time. Whether this is a step up, down or sideways is left as an exercise for the reader.
Python has also as we have alluded earlier, a number of complex protocol implementations available over the top of this low-level access to the net. These make light work of much of the sort of network interaction which we wish to do most commonly. Of particular note are the Web based protocols and the support for manipulating the data which might be retrieved using them. It is interesting to note that the Infoseek Web Search engine is purported to be implemented in Python and I presume that the some of Python's abilities in this regard have fed off that development and perhaps vice versa.
Also of note, Python has good support for demangling the rather bizarre and more than a little rococo structure of the CGI interface presented by the mainstream HTTP servers. This means that Python is a good fit for building that level of Web infrastructure too.
Having provided a rich set of protocol support and the ability to manipulate HTML, SGML, URL's, images and sound, the temptation to take the final step and build a complete Web browser around these pieces must not merely be great but be unsurprising.
Grail, is the product of this effort. Grail is a Web browser written entirely in Python just as HotJava was a browser written entirely in Java. Like its commercial counterpart, having an interpretive engine at its lowest level means that given support for downloading content from a Web server, the Grail browser can then allow that content to run and provide the same sorts of dynamic content which Java is currently being used for. Unlike Java, with its strong commitment to security, such downloaded Python has more questionable restrictions placed on it. This is clearly a place where you will wish to tread carefully.
In spite of this, Grail has other things to offer a potential user. Like Python, Grail is free and we are told is easily extended to offer new functionality. This may be quite useful in intranets where a browser interface can handle much of the corporate data but some extra facilities are required. For example, a medical imaging system could have fixed data on screen, live data coming in to a Python applet and have an extra interface to control a live video window with say real-time data from a 3D imaging system.
The key here is that the Python interpreter may be wired into any other program so that it either runs a whole Python application or issues a command prompt or calls into a specific function in a Python module to perform a specific service. This latter method is provided as a set of changes to the popular Apache HTTP daemon which allows it to execute Python programs (which are presumed to provide HTML for the server to send to the client).
Extending python can be attractive for a number of reasons. The first is the extra hardware discussion we had above. If we want to drive some new hardware, the chances are we will need some special code to open the device, and manipulate it. This is a place where a small extension module can pay big dividends. The other occasion where you might be tempted to code an extension is where you have a built a Python application, profiled it and found a large hotspot with the profiling tools. By recoding the offending code in C and extending the Python interpreter this way, you may make the solution of your problem much more efficient.
Some of the other extensions are less mainstream and hence will garner less support and be less devastating if they fail to arrive or be useful. These mooted APIs are:
Finally, the comp.lang.python newsgroup is a good forum for discussing language features. As ever though, it not likely to be wise to go there asking for beginners tutorial instruction. Like most newsgroups they like to think you've made some effort yourself first before bothering the entire world at once.
|||Programming Python, Mark Lutz, O'Reilly & Associates, 1996, 880pp
|||Internet Programming with Python, Aaron Watters, Guido Van Rossum,
James C. Ahlstrom, M&T Books, 1996, 477pp, (include CD-ROM)