On Fri, 2003-09-26 at 12:20, Tim Hochberg wrote:
Todd Miller wrote: I'd make the same comment for this case as for the above case except that all else being equal, subclasses should prevail over superclasses.
I don't have a solution yet, but am hopeful that more free candy will fall from the sky... or YAGNI. Perry pointed out that similar problems exist for *any* Python class hierarchy, so we're not alone, and perhaps should forget about this until it matters. If someone sees an easy fix, now would be better than later.
Here's some quick thoughts. In order for this to work out sensibly you want the order between classes to be transistive and you probably also always want to be able to insert a class into the order between any two classes This is equivalent to deciding the op priority based on a comparison based on some real number associated with each class. This leads to something like:
Once again I think your ideas solve the problem, so thanks. I have a few things I wanted to bounce off you.
class NumArrayFamily: op_priority = 0.0
# This makes it compatible with the current proposal , but isn't strictly necessary. class DeferredToByNumarray(NumArrayFamily): op_priority = 1000.0
class NumArrary(..., NumArrayFamily): # ... def __add__(self, object): if isinstance(object, NumArrayFamily): if ((object.op_priority > self.object.op_priority) or (object.op_priority == self.object.op_priority) and issubclass(object, self.__class__)): return other.__radd__(self) return ufunc.add(self, other)
class MySubclassOfNumarray(NumArray): op_priority = 10.0 # deffered to by NumArray, but defers to DeferredToByNumarray classes.
As I understand it, 2.2 new style object subclass r-operators automatically get priority (subclass.__radd__ is called in preference to superclass.__add__). I think this has two implications: 1) the ==/subclass term won't work, because __add__ will never get called. 2) we have to redefine __radd__ as well to implement the priority scheme. I'm not sure the isinstance is necessary for __radd__, but I like the symmetry. How does this look: class DeferredToByNumArray: # name seems a little off now, but whatever pass class NumArray(..., DeferredToByNumArray): op_priority = 0 def __add__(self, object): if (isinstance(object, DeferredToByNumArray) and object.op_priority > self.op_priority): return object.__radd__(self) return ufunc.add(self, object) def __radd__(self, object): if (isinstance(object, DeferredToByNumArray) and object.op_priority > self.op_priority): return object.__add__(self) return ufunc.add(object, self) class MyForeignClass(DeferredToNumArray): op_priority = 1.0 class MySubclassOfNumArray(NumArray): op_priority = -1.0
Of course the user still has to be careful to make sure the priority order makes sense and you could have big problems when combining packages with disprate ideas about priority levels, but I'm not sure how you can get away from that.
As long as there's a scheme in place to resolve potential conflicts with a little discussion, I think your solution is already ahead of the demand. I told Colin last week I'd raise this issue on c.l.py. I have decided not to (although someone else could obviously do it if they are still concerned about it), because (a) the problem is solved, (b) explaining the problem well enough to get usable input is difficult and I've got other stuff to do. Thanks again for these ideas, Todd -- Todd Miller <jmiller@stsci.edu>