Question about 'None'

Steven Bethard steven.bethard at gmail.com
Thu Jan 27 16:07:40 EST 2005


Francis Girard wrote:
> Le jeudi 27 Janvier 2005 21:29, Steven Bethard a écrit :
>>
>>So None being smaller than anything (except itself) is hard-coded into
>>Python's compare routine.  My suspicion is that even if/when objects of
>>different types are no longer comparable by default (as has been
>>suggested for Python 3.0), None will still compare as smaller than
>>anything...
> 
> Well, here's python doesn't seem to confirm what you're saying :
> 
> 
>>>>a = "10"
>>>>b = 10
>>>>a > b
> 
> True
> 
>>>>b > a
> 
> False
> 
>>>>id(a)
> 
> 1077467584
> 
>>>>id(b)
> 
> 134536516

Actually, this code doesn't contradict what I said at all.  I said that 
None (and only None) was special-cased.

> It really looks like the addresses are compared when objects are of different 
> types if there is no __cmp__ or __lt__ user made specification to compare 
> objects of different types.

Use the source Luke! ;)  Download it from CVS and take a look.  The end 
of default_3way_compare:

static int
default_3way_compare(PyObject *v, PyObject *w)
{
	...
	/* None is smaller than anything */
	if (v == Py_None)
		return -1;
	if (w == Py_None)
		return 1;

	/* different type: compare type names; numbers are smaller */
	if (PyNumber_Check(v))
		vname = "";
	else
		vname = v->ob_type->tp_name;
	if (PyNumber_Check(w))
		wname = "";
	else
		wname = w->ob_type->tp_name;
	c = strcmp(vname, wname);
	if (c < 0)
		return -1;
	if (c > 0)
		return 1;
	/* Same type name, or (more likely) incomparable numeric types */
	return ((Py_uintptr_t)(v->ob_type) < (
		Py_uintptr_t)(w->ob_type)) ? -1 : 1;
}

So it looks like Python uses the type name.  Testing this:

py> A = type('A', (object,), {})
py> Z = type('Z', (object,), {})
py> lst = [str('a'), dict(b=2), tuple(), Z(), A()]
py> [type(o).__name__ for o in lst]
['str', 'dict', 'tuple', 'Z', 'A']
py> sorted(type(o).__name__ for o in lst)
['A', 'Z', 'dict', 'str', 'tuple']
py> sorted(lst)
[<__main__.A object at 0x011E29D0>, <__main__.Z object at 0x011E29F0>, 
{'b': 2}, 'a', ()]

Yup.  Looks about right.  (Note that the source code also special-cases 
numbers...)

So, the order is consistent, but arbitrary, just as Fredrik Lundh 
pointed out in the documentation.

Steve



More information about the Python-list mailing list