else
refers to, so there is no ambiguity.
__add__
. C++ would call it
operator+
; Sather would call it plus
.
self.__class__
instead of
complex
.
We will return to the meta-question in the Sather treasure hunt.
def flatten(s): r = [] for elt in s: for subelt in elt: r.append(subelt) return r # Flatten 1 level, not assuming that s is a sequence of sequences. def flatten2(s): r = [] for elt in s: try: for subelt in elt: r.append(subelt) except TypeError: r.append(elt) return r def superflatten(s): result = [] for i in s: try: result = result + superflatten(i) except TypeError: result.append(i) return result
def make_mult(a): return lambda b, aa=a: lambda x, aaa=aa, bb=b: aaa*x + bb
Based on this behavior, Python's inheritance model can be described as
a chain of responsibility. Instances are initially empty, and pass
the buck on to their classes, which may pass the buck on to their
superclasses. Assignment always creates a local "shadow", which is
removed by del
. This is different from most other
object-oriented languages, which either (1) do not propagate class changes
or (2) share class variables among all instances.
The suggested unification can be implemented by tables which have a programmer-controlled parent pointer. The pointer provides the link in the chain of responsibility. This is the approach taken by our next language, Self.
However, this seems at odds with security, since a typo in an lvalue will go unnoticed. In the non-scripting languages, this error can happen too, but only if there is a matching global, and globals tend to be rare in those languages. (Perhaps for precisely this reason.)
Using assign-global
/assign-local
interchangeably
could be implemented by allowing globals to be renamed within a block which
used a local with the same name. Tcl's upvar
command allows
this; scant other languages support it. upvar
is the
linguistic analogue of UNIX symbolic links. Tcl also allows you to
traverse up the block stack similar to UNIX's "..".
Python not only defaults to local assignment in a block but also in a
class. Let's explore the connection between class inheritance and block
nesting. An assign-global
statement for a class member would
amount to skipping this class and performing the assignment in the
superclass, which can be done by writing self.__class__.x
instead of self.x
. Thus we see that classes already have the
flexibility we want from blocks. Classes can access their parents,
obviating the local/global distinction, while code blocks cannot. Indeed,
classes were invented in Simula 67 precisely for the purpose of
generalizing lexical blocks. Strange how few languages exploit this.