En Tue, 15 May 2007 14:01:20 -0300, [EMAIL PROTECTED] <[EMAIL PROTECTED]> escribió:
> On May 15, 12:30 am, "Gabriel Genellina" <[EMAIL PROTECTED]> > wrote: >> And said section 5.9 should be updated too: "The objects need not have >> the >> same type. If both are numbers or strings, they are converted to a >> common >> type. > > Except when they aren't. I think you don't get the difference between a builtin object, fully under the Python developers' control, and a user defined class that can behave arbitrarily at wish of its writer and for which the Python documentation barely can say a word. The docs say how will the Python interpreter try to compare objects (invoke the rich comparison methods, invoke __cmp__, etc) and how the *builtin* objects behave. For other objects, it's up to the object *writer* to provide such methods, and he can do whatever he wishes: py> class Reversed(int): ... def __lt__(self, other): return cmp(int(self),other)>0 ... def __gt__(self, other): return cmp(int(self),other)<0 ... def __le__(self, other): return cmp(int(self),other)>=0 ... def __ge__(self, other): return cmp(int(self),other)<=0 ... py> py> j=Reversed(6) py> j==6 True py> j>5 False py> j>10 True py> j<=5 True You can't blame Python for this. >>>> import gmpy >>>> a = 2**177149-1 >>>> b = gmpy.mpz(2**177149-1) >>>> a==b > True >>>> print '%d' % (b) > > Traceback (most recent call last): > File "<pyshell#4>", line 1, in <module> > print '%d' % (b) > TypeError: int argument required > > So although the comparison operator is smart enough to realize > the equivalency of numeric types and do the type conversion, > the print statement isn't so smart. This is up to the gmpy designers/writers/maintainers. Anyone writing a class chooses which features to implement, which ones to omit, how to implement them, etc. The code may contain bugs, may not be efficient, may not behave exactly as the users expect, may not have anticipated all usage scenarios, a long etc. In this case, probably the gmpy writers have chosen not to allow to convert to int, and they may have good reasons to not do that (I don't know what platform are you working in, but I feel that your b object is somewhat larger than sys.maxint...). >> Otherwise, objects of different builtin types always compare >> unequal, and are ordered consistently but arbitrarily. You can control >> comparison behavior of objects of non-builtin types by defining a >> __cmp__ >> method or rich comparison methods like __gt__, described in section >> 3.4." >> >> I hope this helps a bit. Your performance issues don't have to do with >> the >> *definition* of equal or not equal, > > I didn't say that, I said the performance issues were related > to type conversion. Can you explain how the "definition" of > equal does not involve type conversion? There is no type conversion involved for user defined classes, *unless* the class writer chooses to do so. Let's invent some new class Number; they can be added and have basic str/repr support py> class Number(object): ... def __init__(self, value): self.value=value ... def __add__(self, other): return Number(self.value+other.value) ... def __str__(self): return str(self.value) ... def __repr__(self): return 'Number(%s)' % self.value ... py> x = Number(2) py> y = Number(3) py> z = x+y py> z Number(5) py> z == 5 False py> 5 == z False py> z == Number(5) False py> int(z) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: int() argument must be a string or a number py> "%d" % z Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: int argument required You can't compare them to anything, convert to integer, still nothing. Let's add "int conversion" first: py> Number.__int__ = lambda self: int(self.value) py> int(z) 5 py> "%d" % z '5' py> z == 5 False py> 5 == z False Ok, a Number knows how to convert itself to integer, but still can't be compared successfully to anything. (Perhaps another language would try to convert automagically z to int, to compare against 5, but not Python). Let's add basic comparison support: py> Number.__cmp__ = lambda self, other: cmp(self.value, other.value) py> z == Number(5) True py> z > Number(7) False py> z == z True py> z == 5 Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 1, in <lambda> AttributeError: 'int' object has no attribute 'value' Now, a Number can be compared to another Number, but still not compared to integers. Let's make the comparison a bit smarter (uhm, I'll write it as a regular function because it's getting long...) py> def NumberCmp(self, other): ... if isinstance(other, Number): return cmp(self.value, other.value) ... else: return cmp(self.value, other) ... py> Number.__cmp__ = NumberCmp py> z == 5 True py> z == 6 False py> 5 == z True As you can see, until I wrote some code explicitely to do the comparison, and allow other types of comparands, Python will not "convert" anything. If you find that some class appears to do a type conversion when comparing instances, it's because the class writer has explicitely coded it that way, not because Python does the conversion automagically. >> only with how someone decided to write the mpz class. > I'm beginning to think there's a problem there. Yes: you don't recognize that gmpy is not a builtin package, it's an external package, and its designers/writers/implementors/coders/whatever decide how it will behave, not Python itself nor the Python developers. -- Gabriel Genellina -- http://mail.python.org/mailman/listinfo/python-list