Appendix A. A Selective and Impressionistic Short Review of Python
A reader who is coming to Python for the first time would be well served reading Guido van Rossum's Python Tutorial , which can be downloaded from < http://python.org/ > , or picking up one of the several excellent books devoted to teaching Python to novices. As indicated in the Preface, the audience of this book is a bit different.
The above said, some readers of this book might use Python only infrequently, or not have used Python for a while, or may be sufficiently versed in numerous other programming languages, that a quick review on Python constructs suffices for understanding. This appendix will briefly mention each major element of the Python language itself, but will not address any libraries (even standard and ubiquitous ones that may be discussed in the main chapters). Not all fine points of syntax and semantics will be covered here, either. This review, however, should suffice for a reader to understand all the examples in this book.
Even readers who are familiar with Python might enjoy skimming this review. The focus and spin of this summary are a bit different from most introductions. I believe that the way I categorize and explain a number of language features can provide a moderately novelbut equally accurateperspective on the Python language. Ideally, a Python programmer will come away from this review with a few new insights on the familiar constructs she uses every day. This appendix does not shy away from using some abstract terms from computer scienceif a particular term is not familiar to you, you will not lose much by skipping over the sentence it occurs in; some of these terms are explained briefly in the Glossary.
A.1 What Kind of Language Is Python?
Python is a byte-code compiled programming language that supports multiple programming paradigms. Python is sometimes called an interpreted and/or scripting language because no separate compilation step is required to run a Python program; in more precise terms, Python uses a virtual machine (much like Java or Smalltalk) to run machine-abstracted instructions. In most situations a byte-code compiled version of an application is cached to speed future runs, but wherever necessary compilation is performed "behind the scenes."
In the broadest terms, Python is an imperative programming language, rather than a declarative (functional or logical) one. Python is dynamically and strongly typed, with very late binding compared to most languages. In addition, Python is an object-oriented language with strong introspective facilities, and one that generally relies on conventions rather than enforcement mechanisms to control access and visibility of names. Despite its object-oriented core, much of the syntax of Python is designed to allow a convenient procedural style that masks the underlying OOP mechanisms. Although Python allows basic functional programming (FP) techniques, side effects are the norm, evaluation is always strict, and no compiler optimization is performed for tail recursion (nor on almost any other construct).
Python has a small set of reserved words, delimits blocks and structure based on indentation only, has a fairly rich collection of built-in data structures, and is generally both terse and readable compared to other programming languages. Much of the strength of Python lies in its standard library and in a flexible system of importable modules and packages.
A.2 Namespaces and Bindings
The central concept in Python programming is that of a namespace. Each context (i.e., scope) in a Python program has available to it a hierarchically organized collection of namespaces; each namespace contains a set of names, and each name is bound to an object. In older versions of Python, namespaces were arranged according to the "three-scope rule" (builtin/global/local), but Python version 2.1 and later add lexically nested scoping. In most cases you do not need to worry about this subtlety, and scoping works the way you would expect (the special cases that prompted the addition of lexical scoping are mostly ones with nested functions and/or classes).
There are quite a few ways of binding a name to an object within the current namespace/scope and/or within some other scope. These various ways are listed below.
A.2.1 Assignment and Dereferencing
A Python statement like x=37 or y="foo" does a few things. If an objecte.g., or "foo" does not exist, Python creates one. If such an object does exist, Python locates it. Next, the name x or y is added to the current namespace, if it does not exist already, and that name is bound to the corresponding object. If a name already exists in the current namespace, it is re-bound. Multiple names, perhaps in multiple scopes/namespaces, can be bound to the same object.
A simple assignment statement binds a name into the current namespace, unless that name has been declared as global. A name declared as global is bound to the global (module-level) namespace instead. A qualified name used on the left of an assignment statement binds a name into a specified namespaceeither to the attributes of an object, or to the namespace of a module/package; for example:
>>> x = "foo" # bind 'x' in global namespace>>> def myfunc(): # bind 'myfunc' in global namespace... global x, y # specify namespace for 'x', 'y'... x = 1 # rebind global 'x' to 1 object... y = 2 # create global name 'y' and 2 object... z = 3 # create local name 'z' and 3 object...>>> import package.module # bind name 'package.module'>>> package.module.w = 4 # bind 'w' in namespace package.module>>> from mymod import obj # bind object 'obj' to global namespace>>> obj.attr = 5 # bind name 'attr' to object 'obj'
Whenever a (possibly qualified) name occurs on the right side of an assignment, or on a line by itself, the name is dereferenced to the object itself. If a name has not been bound inside some accessible scope, it cannot be dereferenced; attempting to do so raises a NameError exception. If the name is followed by left and right parentheses (possibly with comma-separated expressions between them), the object is invoked/called after it is dereferenced. Exactly what happens upon invocation can be controlled and overridden for Python objects; but in general, invoking a function or method runs some code, and invoking a class creates an instance. For example:
>>> pkg.subpkg.func() # invoke a function from a namespace>>> x = y # deref 'y' and bind same object to 'x'
A.2.2 Function and Class Definitions
Declaring a function or a class is simply the preferred way of describing an object and binding it to a name. But the def and class declarations are "deep down" just types of assignments. In the case of functions, the lambda operator can also be used on the right of an assignment to bind an "anonymous" function to a name. There is no equally direct technique for classes, but their declaration is still similar in effect:
>>> add1 = lambda x,y: x+y # bind 'add1' to function in global ns>>> def add2(x, y): # bind 'add2' to function in global ns... return x+y...>>> class Klass: # bind 'Klass' to class object... def meth1(self): # bind 'meth1' to method in 'Klass' ns... return 'Myself'
A.2.3 import Statements
Importing, or importing from, a module or a package adds or modifies bindings in the current namespace. The import statement has two forms, each with a bit different effect.
Statements of the forms
>>> import modname>>> import pkg.subpkg.modname>>> import pkg.modname as othername
add a new module object to the current namespace. These module objects themselves define namespaces that you can bind values in or utilize objects within.