[Compiler-sig] Polymorphism/encapsulation in Python

John Max Skaller skaller@maxtal.com.au
Thu, 06 Apr 2000 02:48:37 +1000


Rafael H Schloming wrote:
> 
> >       Object orientation is what makes
> > Java counter-intuitive. Python, in many ways, is NOT restricted by
> > a static type system, and therefore not restricted by a broken
> > one like Java's. Instead, python programming is based on notions of
> > protocols, such as 'sequence', where a mix of lightweight functional,
> > procedural, and object oriented programming techniques coupled with
> > dynamic typing, provide highly flexible notions of interfaces,
> > not represented in the language (as they are in Java, Eiffel,
> > and typically in C++ as well).
> 
> What exactly is the difference between protocals and interfaces? 

	A protocol is a set of rules for using components together.
Usually these rules are written down in news articles, documentation,
etc: these things are partly designed, and partly established by
practice with experience of using certain techniques.

	An interface is a way of _enforcing_ part of a protocol.
For example, there is no encapsulation in Python: there are no
interfaces to enforce it. However, you can program with the convention
that private methods start with an underscore (_), and that you will
NEVER set or get data attributes from a class instance. You TELL
people using your class not to do it 'or on their head be it' :-)

> I always looked at python as a language that makes very heavy use of
> interfaces

	This is not really correct in Python. [Although
the syntax is vaguely related to the protocols .. this is true
in any language :-] Strangely, it IS correct
when writing Python _extensions_. In this case, some of the
protocols are embodied in generic functions of the C API:
have a look at the documentation on the C API and notice it is divided
into levels such as 'abstract objects layer', etc.

> and therefore just about any code you write to operate on
> lists or strings ends up working on anything satisfying the sequence
> interface. Personally I think making this explicit would be a great
> idea.

	What you say is common, and when you say 'making it explicit'
I think you mean 'with language constructions (such as interfaces)'.
The implication of these constructions is _enforcement_.

	Aka 'baby sitting' :-) 

	Secondly, I agree with you that making it explicit would
be a good idea.

	If only we knew how to do this. The problem is, we don't.

	To learn about interfaces, you must use a 'well-typed' programming
language like ML. I recommend ocaml or haskell. You cannot learn about
this from silly stuff like java. Actually, Python is also good,
because you can experiment with 'typing ideas', without enforcement
getting in the way.

	Consider the following python function:

	def f(x): f

Exactly how would you 'type' this function f?
This function is not useful. But the following one, in C++, truly is:

	ptm continuation() { ... }

where the type of the function 'continuation' is 'pointer to member
of the type of continuation'.

	You may wonder on the use of this function.
It is the function which drives an callback driven interpreter.
(you call some method on an object, and it returns the next
method to execute: this method has the same type as the method
returning it).

> I've written large scale software in python that had very complicated
> class heirarchies with litteraly thousands of different classes. I
> think python scaled very well to this level 

	From your description I'd guess this would be about the end
of it's scalability.

> and I would choose it over any other language, 

	I wouldn't, unless Python offered some special advantage.
My own 'medium' sized python program interscript -- which is
much smaller than yours -- has reached the point where the lack 
of static typing and more powerful constructions, has made the code
very hard to maintain.

> but what I found myself doing was putting in an
> assert for every single argument in order to catch little slips like
> swapping two arguments or passing in the wrong value somewhere.
> Without these asserts the system would have been difficult to debug
> because the errors wouldn't show up until very far beyond the place
> where the actual bug occured. An interface mechanism would have
> allowed me to express my asserts much more tersely and would have made
> my code far more generic since I would be asserting things like
> arg_foo satisfies interface bar instead of isinstance(arg_foo, ClassBar)
> where ClassBar is just a specific implementation of interface bar.

	No one disagrees with this. The question is how to do it.
I have my own 'python' interpreter, (Vyper) which is considerbly more
powerful
than Python. It has superior static control, for example: fully nested
scoping, 'compiling' all static variables [CPython does this now,
but only for function locals]

	It has superior techniques for interface specification:
nested modules, hiding of temporaries using with/do blocks,
renaming imported symbols (import x as y), pattern matching,
Greg Stein's typecheck operator x ! t, both dynamically,
and also in function declarations where there is opportunity
for compile time type checking (although I do not yet do this in Vyper).

	These abilities are not the same as a full scale static type
system. But they permit _more_ checking at compile time, while hopefully
not preventing uncluttered expression, nor generating weird error
messages
(symptoms of systems which require everything be declared (C++), and
those using type inference to deduce types, respectively).


-- 
John (Max) Skaller, mailto:skaller@maxtal.com.au
10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850
checkout Vyper http://Vyper.sourceforge.net
download Interscript http://Interscript.sourceforge.net