[Tutor] Beginner's question
eryksun
eryksun at gmail.com
Thu Nov 22 20:50:39 CET 2012
On Thu, Nov 22, 2012 at 10:49 AM, Dave Angel <d at davea.name> wrote:
>
>> x, y, z = 26, 15, 20
>>
>> largest = None
>> if x %2:
>> largest = x
>> if y % 2:
>> if y > largest:
>> largest = y
>> if z % 2:
>> if z > largest:
>> largest = z;
>>
>> if Largest:
>> print "largest value is", largest
>> else:
>> print "no odd values"
>>
>
> This one first gets into trouble if x is even and y is odd, because if
> tries to compare y with None, which is basically an undefined ordered
> comparison (and illegal in Python3, I believe). The flag value needs to
> be an int, or at least numeric.
Yes, comparing an int to None raises a TypeError in Python 3, but it
is 'defined' in 2.x, for what it's worth. Since
NoneType lacks tp_richcompare (__lt__, __gt__, etc)
NoneType lacks tp_compare (__cmp__)
int/long lack tp_richcompare for a swapped operation
int/long tp_compare isn't _PyObject_SlotCompare
None can't be coerced (__coerce__) to an int/long
the comparison falls through to default_3way_compare, where it's hard coded:
/* None is smaller than anything */
if (v == Py_None)
return -1;
if (w == Py_None)
return 1;
http://hg.python.org/cpython/file/70274d53c1dd/Objects/object.c#l750
If you want a warning for this, start the interpreter with the -3
flag. The first time you try to compare None to a number in your code
(except for EQ/NE), you'll get a deprecation warning:
>>> None < -1
__main__:1: DeprecationWarning: comparing unequal types not
supported in 3.x
True
Also, "smaller than anything" only applies to the default case, after
having exhausted all other avenues. You can make your own type that's
'smaller' than anything, including None:
import functools
@functools.total_ordering
class LT(object):
def __eq__(self, other):
return isinstance(other, LT)
def __lt__(self, other):
if isinstance(other, LT):
return False
return True
def max_odd(seq, reduce=functools.reduce):
sentry = LT()
test = lambda x, y: y if y % 2 and y > x else x
result = reduce(test, seq, sentry)
if result == sentry:
raise ValueError("No odd numbers")
return result
You can unroll the reduction as a chain of statements as Joel did, if
you have to. Just replace "largest = None" with "largest = sentry =
LT()".
More information about the Tutor
mailing list