[Tutor] changes in Python 2.2

Kirby Urner urnerk@qwest.net
Tue, 25 Jun 2002 22:41:46 -0700


[Warning to the reader:  the remarks below reflect my current understanding
of where Python is going which may be inaccurately or misleadingly
expressed in some details.  Corrections welcome.]

Just responding to this thread about new features in more recent
Pythons (and did you read about the boolean type? -- sounds good
to me)....

 > Something has been gained, but I am afraid - much also lost.
 >
 > But its a definite sore point topic in the community - at all
 > levels of involvement.
 >
 > I am not meaning to bring the discussion here.
 >
 > But I do think a "rounded" answer to the question is appropriate.
 >
 > Art

I think we should also recognize that the designers have the
challenge of evolving the language in ways that aren't too
disruptive of working code, so that people who choose to upgrade
aren't overly penalized.

It's healthy for the language if the most experienced users don't
feel too stuck in the older versions.

But this incremental approach means streamlining simplifications
can't be implemented as cleanly as if this were a blank slate
situation. So in some respects, the 2.x versions are messier
than the final result, because they're transitioning between
paradigms in a rather subtle way (so as to not lose too many
people by breaking a lot of code all at once).

Being able to subclass builtin classes like lists is actually a
simplification, adds consistency to the "everything is an object"
abstraction.  When I found you could go:

  >>> 3 .__add__(5)  # note: a space before the .
  8

my appreciation for the internal consistency of the emerging model
increased.  This makes Python easier to teach (  I can say to kids:
"see, the built-in int type has an __add__ method just like a user-
defined class might, and we'd normally trigger it using the + operator).

But in order to be able to subclass builtins, a base object (mother of
all objects) had to be introduced at the root of the class hierarchy.
In recent versions, this root class (named object) has to be inherited
from explicitly, as in:

  >>> class Newclass(object):
         pass

# lets look at the methods the Mother of all Objects supports:

  >>> o = Newclass()    # make an instance

  >>> dir(o)
  ['__class__', '__delattr__', '__dict__', '__getattribute__',
  '__hash__', '__init__', '__module__',  '__new__', '__reduce__',
  '__repr__', '__setattr__', '__str__', '__weakref__']

Some familiar methods there (__add__ comes in further down in the
tree).

And what's the base class of a primitive type?

  >>> list.__base__
  <type 'object'>
  >>> int.__base__
  <type 'object'>

Same as my Newclass.

This design approach, of anchoring the class hierarchy to a single
top-level object is not unusual.  It's what Java and SmallTalk both do
(but not C++).  Builtins and user-defined classes will all inherit
from a single root (even if multiple inheritance is supported
further down on the tree).  Types and classes unify (to define a
class is to define a type).

  >>> type(o)  # not just an "instance type"
  <class '__main__.Newclass'>

In contrast (old style class):

  >>> class Oldclass:  # not inheriting from object
         pass

  >>> o = Oldclass()

  >>> dir(o)  # not much to inherit
  ['__doc__', '__module__']

  >>> type(o)  # not very explicit about type, either
  <type 'instance'>

Eventually, in later versions, you won't need to explicitly subclass the
Mother Object to inherit her properties -- that'll be presumed.  But given
the incremental approach, there's an interim period when both old and
new styles of classes need to be supported.

Likewise, they can't just drop the L from long integers overnight -- some
code still expects to find it:

  >>> 1834091830981093401834018304918340123  # note L appended below
  1834091830981093401834018304918340123L
                                       ^
                                   going away

Kirby