[Python-Dev] Re: PyNumber_Check()

Guido van Rossum guido@python.org
Mon, 18 Nov 2002 13:02:07 -0500

> > No, I think PyNumber_Check() should be deprecated.  I don't think
> > there's a valid use case for it.  If you really want a fuzzy
> > definition like "at least one of nb_int, nb_long, nb_float is
> > available", you can test for that yourself -- IMO that doesn't really
> > make it a number.
> Hmm, I use it in mxODBC to switch on Python object types.
> The above change causes the semantics to change as well:
>              ...
> 	    else if (PyNumber_Check(v)) {

When you pass a class instance that doesn't support __float__, you'll
get an error from the code below:

> 		if (mxODBC_DateStructFromFloat(dbcs, v, param, row)) {
> 		    if (!PyErr_Occurred())
> 			PyErr_Format(PyExc_TypeError,
> 	   "parameter %i in row %i must be a mxODBC date float",
> 				     column, row);
> 		    goto onError;
> 		}
> 	    }
> 	    else if (PyString_Check(v)) {
> 		param->data = (SQLPOINTER)(PyString_AS_STRING(v));
> 		param->data_len = strlen(PyString_AS_STRING(v));
> 		param->ctype = SQL_C_CHAR;
> 	    }
> With the new semantics, the PyNumber_Check() test would
> succeed for strings, making the second test a no-op.
> I would expect that this kind of switching on types is
> not uncommon for code which works in polymorphic ways.

Alas, I agree with this expectation, even though I believe that such
code is based on a misunderstanding. :-(

> > PyNumber_Check() comes from an old era, when the presence or absence
> > of the as_number "extension" to the type object was thought to be
> > useful.  If I had to do it over, I wouldn't provide PyNumber_Check()
> > at all (nor PySequence_Check() nor PyMapping_Check()).
> Ok, but why not fix those APIs to mean something more
> useful than deprecating them ? E.g. I would expect that
> a number is usable as input to float(), int() or long()
> and that a mapping knows at least about __getitem__.

Maybe, as long as we all agree that that's *exactly* what they check
for, and as long as we agree that there may be overlapping areas
(where two or more of these will return True).

PyMapping_Check() returns true for a variety of non-mappings like
strings, lists, and all classic instances.

--Guido van Rossum (home page: http://www.python.org/~guido/)