views:

105

answers:

6

Is there any way to have Python operators line "==" and ">" return ints instead of bools. I know that I could use the int function (int(1 == 1)) or add 0 ((1 == 1) + 0) but I was wondering if there was an easy way to do it. Like when you want division to return floats you could type from __future__ import division. Is there any way to do this with operators returning ints? Or could I make a class extending __future__._Feature that would do what I want?

+3  A: 

You cant override the built-in comparison functions. In some sense the comparison operators are already returning int. bool is a subclass of int, so you can do anything to it that you can do to a int. The question then becomes why would you want to have comparisons return int objects, not bool objects?

Ants Aasma
+1  A: 

You can have the comparison operators of your custom classes return whatever you like -- simply implement the relevant methods (__eq__, __ne__, __gt__, __lt__, __ge__, __le__) to return what you want. For objects that you don't control you cannot change this, but there should be no need to: bools are ints, because of the Liskov substitution principle. Code that notices a difference between the bool returned by the builtin types' __eq__ methods and any other integer is using the result wrong.

The __future__ module isn't relevant here; you can't use it to do whatever you want, you can only use it to change specific settings that were added to Python. You can turn division into true division with the __future__ import because that's what was added to Python. The only way to add more __future__ imports is by modifying Python itself.

Thomas Wouters
+1  A: 

Based on your clarification, you might change your comparison operator to something like:

stack.push(1 if stack.pop() > stack.pop() else 0)

This will convert the boolean result of > to 1 or 0 as you would like.

Also, be careful about calling stack.pop() twice in the same expression. You don't know (for sure) what order the arguments will be evaluated in, and different implementations of Python may very well pop the arguments in a different order. You will need to use temporary variables:

x = stack.pop()
y = stack.pop()
stack.push(1 if x > y else 0)
Greg Hewgill
I did the different `stack.pop()`s in the code but was trying to compact them in my comment. Thanks anyway though.
None
The evaluation order of expressions is specified in the language reference (http://docs.python.org/reference/expressions.html#evaluation-order).That said, having function calls with side effects inside a non-trivial expression is usually a bad idea.
Ants Aasma
+1  A: 

On your own objects, it is easy to override each comparison operator. For built-ins, the override methods are "read only" so all my attempts to set them don't pan out.

>>> class foo:
   def __lt__(self, other):
      return cmp(5, other)

>>> f = foo()
>>> f<3
1
>>> f<7
-1
>>> f<5
0

>>> j=""
>>> j.__lt__=lambda other: cmp(5, other)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AttributeError: 'str' object attribute '__lt__' is read-only
Ishpeck
+1  A: 

Cast your bool to an int?

>>> int(True)

1

>>> int(False)

0

Or cast that to a str?

>>> str(int(True))

'1'

>>> str(int(False))

'0'

alxndr
A: 

No, you can't. When Guido unified types and classes, he found a way to override the behavior of built-in types (due to the way he implemented things), but he declared it a bug and plugged the loophole. Changing the behavior of built-in types (except for your example - importing division from future, which is there for a good reason) is forbidden.

Sorry, but I can't find the mailing list post. I remember it though, as it was quite interesting.

wisty