Fw: list.index(..) -> TypeError bug or feature?

(from comp.lang.python) can this be fixed? should this be fixed? (please?) </F> ----- Original Message ----- From: "Pearu Peterson" <pearu@cens.ioc.ee> Newsgroups: comp.lang.python Sent: Tuesday, February 06, 2001 2:42 PM Subject: list.index(..) -> TypeError bug or feature?

Fredrik Lundh wrote:
(from comp.lang.python)
can this be fixed? should this be fixed? (please?)
Depends on whether gmpy (what is this, BTW) uses the old coercion mechanism correctly or not which is hard to say from here ;) Also, was gmpy recompiled for 2.1a2 and which part raised the exception (Python or gmpy) ? In any case, I'd say that .index() should not raise TypeErrors in case coercion fails.
-- Marc-Andre Lemburg ______________________________________________________________________ Company: http://www.egenix.com/ Consulting: http://www.lemburg.com/ Python Pages: http://www.lemburg.com/python/

On Tue, 6 Feb 2001, M.-A. Lemburg wrote:
About gmpy, see http://gmpy.sourceforge.net/
Also, was gmpy recompiled for 2.1a2 and which part raised the exception (Python or gmpy) ?
gmpy was recompiled for 2.1a2, though the same gmpy worked fine with 2.0b2. The exception was raised in gmpy part.
In any case, I'd say that .index() should not raise TypeErrors in case coercion fails.
I fixed this in gmpy source --- there the Pymp*_coerce functions raised an exception instead of returning `1' when coerce failed. So, this was gmpy bug, Python 2.1a2 just revealed it. Regards, Pearu

On Tue, 6 Feb 2001, Fredrik Lundh wrote:
can this be fixed? should this be fixed? (please?)
I'm not sure. The gmpy example:
seems to be just one case of coercion failure. I no longer have Python 2.0 in a state on my machine where i can compile gmpy to test with it, but you can perform the same exercise with the mpz module in 2.1a2: >>> import mpz >>> [mpz.mpz(1), []].index([]) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: number coercion (to mpzobject) failed The following test shows that the issue is present for Python classes too: >>> class Foo: ... def __coerce__(self, other): ... raise TypeError, 'coercion failed' ... >>> f = Foo() >>> s = [3, f, 5] >>> s.index(3) 0 >>> s.index(5) Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 3, in __coerce__ TypeError: coercion failed I get the above behaviour in 1.5.2, 2.0, and 2.1a2. So now we have to ask whether index() should hide these errors. It seems to me that conventional Python philosophy would argue to let the errors flaunt themselves as early as possible, but i agree with you that the failure to find [] in [mpz(1), []] is pretty jarring. ?? Hmm, i think perhaps the right answer is to not coerce before ==, even if we automatically coerce before the other comparison operators. But, this is only good as a future possibility. It can't resolve the issue for existing extension modules because their old-style comparison functions appear to expect two arguments of the same type: (in mpzmodule.c) static int mpz_compare(mpzobject *a, mpzobject *b) { int cmpres; /* guido sez it's better to return -1, 0 or 1 */ return (cmpres = mpz_cmp( &a->mpz, &b->mpz )) == 0 ? 0 : cmpres > 0 ? 1 : -1; } /* mpz_compare() */ ...so the error occurs before tp_compare has a chance to say "okay, it's not equal". We have to ask the authors of extension modules to implement == separately from the other comparisons. Note, by the way, that this re-raises the matter of the three kinds of equality that i remember mentioning back when we were discussing rich comparisons. I'll restate them here for you to think about. The three kinds of equality (in order by strength) are: 1. Identity. Python: 'x is y' E: 'x == y' Python: 'x is not y' E: 'x != y' Meaning: "x and y are the same object. Substituting x for y in any computation makes no difference to the result." 2. Value. Python: 'x == y' E: 'x.equals(y)' Python: 'x != y' E: '!x.equals(y)' Meaning: "x and y represent the same value. Substituting x for y in any operation that doesn't mutate x or y yields results that are ==." 3. Magnitude. Python: missing E: 'x <=> y' Python: missing E: 'x <> y' Meaning: "x and y have the same size. Another way to say this is that both x <= y and x >= y are true." Same identity implies same value; same value implies same magnitude. Category Python operators E operators identity is, is not ==, != value ==, !=, <> x.equals(y), !x.equals(y) magnitude <, <=, >, >= <, <=, >, >=, <>, <=> Each type of equality has a specific and useful meaning. Most languages, including Python, acknowledge the first two. But you can see how the coercion problem raised above is a consequence of the fact that the third category is incomplete. I like Python's spelling better than E's, though it's a small wart that there is no easy way to say or implement 'same magnitude'. (You can get around it by saying 'x <= y <= x', i suppose, but there's no real interface on the C side.) -- ?!ng "There's no point in being grown up if you can't be childish sometimes." -- Dr. Who

On Tue, 6 Feb 2001, Ka-Ping Yee wrote:
I didn't state that last sentence very well, and the table's a bit inaccurate. Rather, it would be better to say that '==' and '!=' end up having to do double duty (sometimes for value equality, sometimes for magnitude equality) -- when really '==' doesn't belong with ordering operators like '<'. It's quite a separate concept. -- ?!ng "There's no point in being grown up if you can't be childish sometimes." -- Dr. Who

Fredrik Lundh wrote:
(from comp.lang.python)
can this be fixed? should this be fixed? (please?)
Depends on whether gmpy (what is this, BTW) uses the old coercion mechanism correctly or not which is hard to say from here ;) Also, was gmpy recompiled for 2.1a2 and which part raised the exception (Python or gmpy) ? In any case, I'd say that .index() should not raise TypeErrors in case coercion fails.
-- Marc-Andre Lemburg ______________________________________________________________________ Company: http://www.egenix.com/ Consulting: http://www.lemburg.com/ Python Pages: http://www.lemburg.com/python/

On Tue, 6 Feb 2001, M.-A. Lemburg wrote:
About gmpy, see http://gmpy.sourceforge.net/
Also, was gmpy recompiled for 2.1a2 and which part raised the exception (Python or gmpy) ?
gmpy was recompiled for 2.1a2, though the same gmpy worked fine with 2.0b2. The exception was raised in gmpy part.
In any case, I'd say that .index() should not raise TypeErrors in case coercion fails.
I fixed this in gmpy source --- there the Pymp*_coerce functions raised an exception instead of returning `1' when coerce failed. So, this was gmpy bug, Python 2.1a2 just revealed it. Regards, Pearu

On Tue, 6 Feb 2001, Fredrik Lundh wrote:
can this be fixed? should this be fixed? (please?)
I'm not sure. The gmpy example:
seems to be just one case of coercion failure. I no longer have Python 2.0 in a state on my machine where i can compile gmpy to test with it, but you can perform the same exercise with the mpz module in 2.1a2: >>> import mpz >>> [mpz.mpz(1), []].index([]) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: number coercion (to mpzobject) failed The following test shows that the issue is present for Python classes too: >>> class Foo: ... def __coerce__(self, other): ... raise TypeError, 'coercion failed' ... >>> f = Foo() >>> s = [3, f, 5] >>> s.index(3) 0 >>> s.index(5) Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 3, in __coerce__ TypeError: coercion failed I get the above behaviour in 1.5.2, 2.0, and 2.1a2. So now we have to ask whether index() should hide these errors. It seems to me that conventional Python philosophy would argue to let the errors flaunt themselves as early as possible, but i agree with you that the failure to find [] in [mpz(1), []] is pretty jarring. ?? Hmm, i think perhaps the right answer is to not coerce before ==, even if we automatically coerce before the other comparison operators. But, this is only good as a future possibility. It can't resolve the issue for existing extension modules because their old-style comparison functions appear to expect two arguments of the same type: (in mpzmodule.c) static int mpz_compare(mpzobject *a, mpzobject *b) { int cmpres; /* guido sez it's better to return -1, 0 or 1 */ return (cmpres = mpz_cmp( &a->mpz, &b->mpz )) == 0 ? 0 : cmpres > 0 ? 1 : -1; } /* mpz_compare() */ ...so the error occurs before tp_compare has a chance to say "okay, it's not equal". We have to ask the authors of extension modules to implement == separately from the other comparisons. Note, by the way, that this re-raises the matter of the three kinds of equality that i remember mentioning back when we were discussing rich comparisons. I'll restate them here for you to think about. The three kinds of equality (in order by strength) are: 1. Identity. Python: 'x is y' E: 'x == y' Python: 'x is not y' E: 'x != y' Meaning: "x and y are the same object. Substituting x for y in any computation makes no difference to the result." 2. Value. Python: 'x == y' E: 'x.equals(y)' Python: 'x != y' E: '!x.equals(y)' Meaning: "x and y represent the same value. Substituting x for y in any operation that doesn't mutate x or y yields results that are ==." 3. Magnitude. Python: missing E: 'x <=> y' Python: missing E: 'x <> y' Meaning: "x and y have the same size. Another way to say this is that both x <= y and x >= y are true." Same identity implies same value; same value implies same magnitude. Category Python operators E operators identity is, is not ==, != value ==, !=, <> x.equals(y), !x.equals(y) magnitude <, <=, >, >= <, <=, >, >=, <>, <=> Each type of equality has a specific and useful meaning. Most languages, including Python, acknowledge the first two. But you can see how the coercion problem raised above is a consequence of the fact that the third category is incomplete. I like Python's spelling better than E's, though it's a small wart that there is no easy way to say or implement 'same magnitude'. (You can get around it by saying 'x <= y <= x', i suppose, but there's no real interface on the C side.) -- ?!ng "There's no point in being grown up if you can't be childish sometimes." -- Dr. Who

On Tue, 6 Feb 2001, Ka-Ping Yee wrote:
I didn't state that last sentence very well, and the table's a bit inaccurate. Rather, it would be better to say that '==' and '!=' end up having to do double duty (sometimes for value equality, sometimes for magnitude equality) -- when really '==' doesn't belong with ordering operators like '<'. It's quite a separate concept. -- ?!ng "There's no point in being grown up if you can't be childish sometimes." -- Dr. Who
participants (4)
-
Fredrik Lundh
-
Ka-Ping Yee
-
M.-A. Lemburg
-
Pearu Peterson