Comparison inconsistency with ExtensionClass

Hi all -- I seem to have discovered an inconsistency in the semantics of object comparison between plain old Python instances and ExtensionClass instances. (I've cc'd python-dev because it looks as though one *could* blame Python for the inconsistency, but I don't really understand the guts of either Python or ExtensionClass enough to know.) Here's a simple script that shows the difference: class Simple: def __init__ (self, data): self.data = data def __repr__ (self): return "<%s at %x: %s>" % (self.__class__.__name__, id(self), `self.data`) def __cmp__ (self, other): print "Simple.__cmp__: self=%s, other=%s" % (`self`, `other`) return cmp (self.data, other) if __name__ == "__main__": v1 = 36 v2 = Simple (36) print "v1 == v2?", (v1 == v2 and "yes" or "no") print "v2 == v1?", (v2 == v1 and "yes" or "no") print "v1 == v2.data?", (v1 == v2.data and "yes" or "no") print "v2.data == v1?", (v2.data == v1 and "yes" or "no") If I run this under Python 1.5.2, then all the comparisons come out true and my '__cmp__()' method is called twice: v1 == v2? Simple.__cmp__: self=<Simple at 1b5148: 36>, other=36 yes v2 == v1? Simple.__cmp__: self=<Simple at 1b5148: 36>, other=36 yes v1 == v2.data? yes v2.data == v1? yes The first one and the last two are obvious, but the second one only works thanks to a trick in PyObject_Compare(): if (PyInstance_Check(v) || PyInstance_Check(w)) { ... if (!PyInstance_Check(v)) return -PyObject_Compare(w, v); ... } However, if I make Simple an ExtensionClass: from ExtensionClass import Base class Simple (Base): Then the "swap v and w and use w's comparison method" no longer works. Here's the output of the script with Simple as an ExtensionClass: v1 == v2? no v2 == v1? Simple.__cmp__: self=<Simple at 1b51c0: 36>, other=36 yes v1 == v2.data? yes v2.data == v1? yes It looks as though ExtensionClass would have to duplicate the trick in PyObject_Compare() that I quoted, since Python has no idea that ExtensionClass instances really should act like instances. This smells to me like a bug in ExtensionClass. Comments? BTW, I'm using the ExtensionClass provided with Zope 2.1.4. Mostly tested with Python 1.5.2, but also under the latest CVS Python and we observed the same behaviour. Greg

Greg Ward wrote:
(demonstration snipped)
Technically, this *is* a bug in ExtensionClass, however, Python *does* deserve some of the blame. The intepreter actually uses the following rule: Instances of two different "python types" are not compared using type-supplied comparison methods unless: - At least one of the types is InstanceType or - Both of the types are numeric. This rule is rather inconvenient for ExtensionClass. It's also pretty inconvenient for non-ExtensionClass non-numeric extension types that want to be comparable with other things. You can work around this by making your ExtensionClass a numeric type. This should be possible by providing a numeric method. Jim -- Jim Fulton mailto:jim@digicool.com Python Powered! Technical Director (888) 344-4332 http://www.python.org Digital Creations http://www.digicool.com http://www.zope.org Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email address may not be added to any commercial mail list with out my permission. Violation of my privacy with advertising or SPAM will result in a suit for a MINIMUM of $500 damages/incident, $1500 for repeats.

"JF" == Jim Fulton <jim@digicool.com> writes:
JF> Instances of two different "python types" are not compared JF> using type-supplied comparison methods unless: JF> - At least one of the types is InstanceType or JF> - Both of the types are numeric. JF> This rule is rather inconvenient for ExtensionClass. JF> It's also pretty inconvenient for non-ExtensionClass JF> non-numeric extension types that want to be comparable with JF> other things. I ran into this problem when trying to translate a simple Boolean class into a built-in type. I basically could not get the comparisons to work correctly when I moved to C. So I'm +1 on fixing this at some point (probably as Guido points out, when we add rich comparisons). -Barry

[JimF]
Without having investigated all the details of this thread, I suspect that all of this ought to be rethought when we do rich comparisons and revamp coercions. I'd say that would be a good project for Python 2.1... (Which most of the Zopers probably still know as 1.7. :-) --Guido van Rossum (home page: http://dinsdale.python.org/~guido/)

Greg Ward wrote:
(demonstration snipped)
Technically, this *is* a bug in ExtensionClass, however, Python *does* deserve some of the blame. The intepreter actually uses the following rule: Instances of two different "python types" are not compared using type-supplied comparison methods unless: - At least one of the types is InstanceType or - Both of the types are numeric. This rule is rather inconvenient for ExtensionClass. It's also pretty inconvenient for non-ExtensionClass non-numeric extension types that want to be comparable with other things. You can work around this by making your ExtensionClass a numeric type. This should be possible by providing a numeric method. Jim -- Jim Fulton mailto:jim@digicool.com Python Powered! Technical Director (888) 344-4332 http://www.python.org Digital Creations http://www.digicool.com http://www.zope.org Under US Code Title 47, Sec.227(b)(1)(C), Sec.227(a)(2)(B) This email address may not be added to any commercial mail list with out my permission. Violation of my privacy with advertising or SPAM will result in a suit for a MINIMUM of $500 damages/incident, $1500 for repeats.

"JF" == Jim Fulton <jim@digicool.com> writes:
JF> Instances of two different "python types" are not compared JF> using type-supplied comparison methods unless: JF> - At least one of the types is InstanceType or JF> - Both of the types are numeric. JF> This rule is rather inconvenient for ExtensionClass. JF> It's also pretty inconvenient for non-ExtensionClass JF> non-numeric extension types that want to be comparable with JF> other things. I ran into this problem when trying to translate a simple Boolean class into a built-in type. I basically could not get the comparisons to work correctly when I moved to C. So I'm +1 on fixing this at some point (probably as Guido points out, when we add rich comparisons). -Barry

[JimF]
Without having investigated all the details of this thread, I suspect that all of this ought to be rethought when we do rich comparisons and revamp coercions. I'd say that would be a good project for Python 2.1... (Which most of the Zopers probably still know as 1.7. :-) --Guido van Rossum (home page: http://dinsdale.python.org/~guido/)
participants (4)
-
bwarsaw@beopen.com
-
Greg Ward
-
Guido van Rossum
-
Jim Fulton