[Python-3000] Implementations: A syntax for extending method dispatching beyond type/class inheritance

Dave Anderson python3000 at davious.org
Thu Dec 7 06:52:35 CET 2006


on 12/3/2006 7:54 PM Bill Janssen wrote:

>> Implementations are used to make Method Dispatching more flexible by 
>> allowing a class to claim that it acts like another class/type even 
>> though it is not derived from that class/type.
> 
> I'm not sure just what this adds over the simple "change_class"
> function that I've posted twice already.  Is there an implementation
> efficiency argument here?

There is more to the syntax sketch than class-vouching.  Duck-typing and 
method-subset implementation declaration/dispatching are included as 
equally visible in this framework.  I'll explain more below.

I've took a couple passes in the archives, and I haven't found the 
change_class posts yet.  I think you are referring to lying about the 
__class__.  Did I guess correctly?  (Sorry, an archive link would help me.)


Inheritance-defined Relationships
=================================

I appreciate the cleanliness of the idea of relating all classes through 
multiple inheritance of either concrete or abstract/type classes.  A 
subset of the syntax sketch supports this (basically as multi-methods 
dispatching by implementations that happen to only use types).

Other-defined Relationships
===========================

Still there are common, if unrefined, conventions of using python I'd 
like to see supported formally as well.

Has-Method Contracts
--------------------

The first thing I loved about python (coming from java), was this 
realization that I was no longer need be caught up in the inheritance 
game.  If I wanted to use an unspoken convention that I could get a 
special string from every object just by defining name() in each of 
those objects, that's all I had to do.  It didn't matter which class 
tree it came from.

Looking at the syntax sketch, this can be formalized; but, its a low 
level of formality that fits the context.

# (I used Generic.name in my original post, but that was a mistake.
#  Sorry for my confusion, Phillip)

def get_name(arg: AnyClass.name):	# AnyClass will magically have
	return arg.name()		# a reference to any method name
					# somehow

further refinement of this would be:

class HasName:
	def name(self):
		...

def get_name(arg: HasName):
	return arg.name()

but this refinement (in the syntax sketch), would force implementers to 
declare the following implementation:

class X:
	implements HasName

	def name(self):
		...


Has Class-specific Method Contracts
-----------------------------------

Similar to Has-Method Contracts are class-specific method contracts.
This is when you use a well-defined class as a way to indicate the 
context of a method and separate it from homonyms.

def add_key_value_pair(arg: MutableContainer.add, key, value):
	arg[key] = value


Implement (As a) vs Inherit (Is a)
----------------------------------

This is nuanced.
Basically, if I have some object Car and I want to be able to use it 
like a dict, I don't necessarily consider it inheriting from dict (or 
even UserDict).  That is, I don't think a Car is a dict.

To me, even if Car happens to represent a dict by being able to be used 
as a dict, the expression of this fact feels better expressed as merely 
implementing dict.

compare:

class Car(dict):	# car... is a dict? hmm, a bad ring to it
	...

class Car:
	implements dict	# oh, Cars can be used like a dict, got it
	...

In addition to that subjective differentiation, there is a technical 
argument.  Without something like an implements declaration, if I ever 
want to express a relationship to another class, but with different 
internals, I am forced to first define an abstract class and then 
inherit from that.  With an implements declaration, I can say implements 
dict and be free of inheriting any of its internal implementation.

(I concede here that I could, in fact, inherit UserDict, override all 
the methods, and just not call super in my init.)

Even with the nicely done ABCs, is there an easy way for a class to 
declare that it can be used like a dict with its own implementation of 
dict methods?  With this syntax sketch, UserDict would remain the same 
except:

class UserDict:
	implements dict		# dispatch can rely on this declaration
	...			# rather than method-checking


The Consequences of Going Outside of the Hierarchy
--------------------------------------------------

For all the above reasons, I want to see python support something more 
flexible than type-based dispatching.  We can look at the method-scoped 
units of Implementations as a limited version of Guido's Abilities, and 
we can look at the class-scoped implementations as types, or classes, or 
  also as abstract interfaces from concrete classes.

Unfortunately, I am now outside of the hierarchy tree; an implementation 
tree would be a superset of a class's hierarchy tree.  I suppose that 
using dispatch this way is more complex compared to a strict class-based 
set of relationships (because I am asking for checks not just on the 
class-tree, but also on the implementations off that class-tree); but, 
I'd rather fold current python usage into a future of type / 
protocol-aware methods than force current pythonists into choosing 
between class or no class, to type or not to type.


(Small Caveat:) Using Implementations as a Development Tool
------------------------------------------------------------

Btw, if we formally differentiate that I'm declaring an implementation 
(versus inherit and override), I could programatically double-check my 
implementation with tools...

class A:
	implements Container

	def len(self)
		...

 >>> interface_compliance(A)

A implements Container:
	methods: len
	missing: get, iterator


> What happens when you call an existing method from one of the
> (supertypes?) of an implementation?  Do you have to re-implement it?
> Or do you have some way of coercing the value to that type?   

In the syntax sketch, an Implementation is basically a list of 
types/class, methods, and other Implementation lists.

You wouldn't call a method from an Implementation object.

(If I missed the gist of these questions.  Please forgive me and clarify 
them for me.)

> 
> Bill
> 
> 


More information about the Python-3000 mailing list