Revision 20 as of 2006-11-30 21:04:24

Clear message

Possible Python 3K Class Tree?

This page contain an incomplete thinking-out-loud description of a re-factoring of the base and built-in Python types into a set of Abstract Base Classes (ABCs) and concrete types. This would probably be a good time to enumerate the exceptions various basic operations can raise, as well.

Some questions:

 equals (Comparable) => Boolean

Object (Comparable):
 hash () => Integer
 # presumable for "is" we compare the ids of the two objects
 id () => Integer

# Why is id an integer?  That is convenient in current CPython
# (which never moves objects, so can use an address), but perhaps
# not in other implementations.  The only real requirement is that
# it be comparable (== and != -- I'm not even sure about sorting)
# to other ids.

 true () => Boolean
 # the __str__ method
 printable () => String

# huh?  Are you saying it has a __str__, or it meets a "printable"
# interface, or ..?

 class () => Type
 implements (Type) => Boolean

Type (Object):
 name () => String
 # supertypes yields list of immediate parent types (what's in __bases__)
 supertypes () => Sequence

# is it strictly a Sequence of Types?  (or types?) 
# (and/or interfaces?)

 # interfaces yields flattened list of all interface types this   
 # implements
 interfaces () => Sequence

Ellipsis (Object):
 # contains only the single value represented by three dots

Null (Object):
 # only a single value of this type

# How is this different from None?  Or are you saying that the
# Null interface is like the NoneType?

Exception (Object):
 args () => Sequence

ExceptionContext (Object):
 exception () => Exception
 traceback () => Traceback

Boolean (Object):

 less_than (Object) => Boolean
 greater_than (Object) => Boolean
# What about <=, >=?
# Currently, only < is used for ordering

 add (Numeric) => Numeric
 subtract (Numeric) => Numeric
 product (Numeric) => Numeric
 quotient (Numeric) => Numeric
 floored_quotient (Numeric) => Numeric
 remainder (Numeric) => Numeric
 negate (Numeric) => Numeric
 absolute_value () => Numeric
 exponentiate (Numeric) => Numeric
 magnitude () => Numeric

Integer (Object, Orderable, Numeric):
 or (Integer) => Integer
 xor (Integer) => Integer
 and (Integer) => Integer
 shift (Integer) => Integer
 invert (Integer) => Integer
 real () => Real

Real (Object, Orderable, Numeric):
 floor () => Integer
 ceiling () => Integer

Complex (Object, Orderable, Numeric):
 conjugate () => Complex

Decimal (Object, Orderable, Numeric):

 iterator () => Iteration

 # yields an iteration of String values

KeyValueIterable (Iterable):
 # yields an iteration of key-value pairs 

Iteration (Object, Iterable):
 next () => other

# should Container be Iterable, or should that be reserved for real types, like Tuple?
Container (Iterable):
 len () => Integer
 contains (Object) => Boolean

Set (Container):
 is_subset (Set) => Boolean
 is_superset (Set) => Boolean
 union_with (Set) => Set
 intersection_with (Set) => Set
 difference (Set) => Set
 symmetric_difference (Set) => Set
 # should this be "multiply" to match Sequence?
 shallow_copy () => Set

Sequence (Container):
 contains (Sequence) => Sequence
 # normal access via index
 # "end" defaults to start, "step" defaults to 1
 slice (Integer start, Integer end = None, Integer step = None) => Object
 # return self + other Sequence
 concatenate (Sequence) => Sequence
 # N shallow copies of self
 multiply (Integer) => Sequence

SequenceOfOrderable (Sequence):
 # do "min" and "max" make sense over arbitrary sequences?  Should really only apply to sequences of "Orderable"
 min () => Orderable
 max () => Orderable

MutableSequence (Sequence):
 append (Object) => self
 insert (Integer position, Object) => self
 # value at I is replaced with Object
 replace (Object, Integer position) => self
 # slice from I to J is replaced with values of Iterator
 replace (Iterable, Integer start, Integer end, Integer step = 1) => self
 extend (Object) => self
 count (Object) => Integer
 reverse ()
 index (Object, Integer start = 0, Integer end = len(self)) => Integer
 pop (Integer position = 0) => Object
 push (Object, Integer position = 0) => self
 delete (Integer start, Integer end = start, Integer step = 1) => self
 sort (Function comparison_fn = None, Function key_fn = None, Boolean reverse = False) => self

ByteSequence (Object, Sequence):
 # should this be a MutableSequence?

Buffer (Object, MutableSequence):
 # is this just mutable version of ByteSequence?

String (Object, Sequence):

Tuple (Object, Sequence):

List (Object, MutableSequence):

 get (Object key, Object default = None) => Object
 set (Object key, Object value)
 # should delete return the deleted value?  Why not.  That removes the need for "pop".
 delete (Object key) => Object
 clear ()
 # shallow copy of mapping
 copy () => Mapping
 contains (Object key) => Boolean
 # items returns a value which is guaranteed to satisfy both the Set interface and the KeyValueIterable interface
 items () => (Set and KeyValueIterable)
 keys () => Set
 values () => Set
 # get_or_set is the current "setdefault"
 get_or_set (Object key, Object value) => Object
 update (Mapping) => self
 # alternate form of "update" takes Iterable of key-value pairs
 update (KeyValueIterable) => self
 # yet another form takes no positional parameters, and arbitrary keyword arguments
 # I need a notation for this kind of method
 update (KWDS) => self
 # do we really need fromkeys?
 fromkeys (Sequence keys, Object initial_value) => Mapping

Dict (Object, Mapping, Container):
 # should some methods (e.g., "fromkeys") be here instead of in Mapping?

 enter () => ExecutionContext
 exit (ExceptionContext) => Boolean

 close ()

 # do we really need to continue to mimic the low-level UNIX seek and tell?
 # why not use Python sequence-style indices for offset?  Positive int for relative
 # to start, negative int for relative to end, and just call tell() and add an offset
 # if  you want to seek relative to the current location, for heaven's sake.
 seek (Integer offset)
 tell () => Integer
BinaryInputStream (Stream):
 # read tries to read the whole file, but may return just a part of it
 read () => ByteSequence
 read (Integer) => ByteSequence

OutputStream (Stream):

 write (ByteSequence) => Integer

 encoding () => String

TextOutputStream (OutputStream, TextStream):
 writeline (String) => Boolean
 writelines (StringIterable) => Boolean

TextInputStream (Stream, TextStream)
 readline () => String
 readlines () => StringIterable

DiskFile (RandomAccessStream):
 fileno () => Integer
 filename () => String
 isatty () => Boolean
 truncate (Integer size)
 mode () => String
 # It would be nice to have another method, "mimetype", which would try to guess
 # the MIME type for the file, and if it can it would return two strings, the MIME major
 # type and minor type for the file.  It would return None, None if it couldn't figure it out.
 # I'd suggest UNIX implementation just use "file", while Windows implementations
 # use registry and file extensions.
 # something like:  mimetype () => String, String


Unable to edit the page? See the FrontPage for instructions.