Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple operators between operands

Tags:

python

Can someone explain why the Python interpreter (2.7.3) gives the following:

>>> 5 -+-+-+ 2

3

Is this ever useful, and for what purpose?

like image 316
Sharp3 Avatar asked Apr 08 '13 23:04

Sharp3


People also ask

Which operators are used with multiple operands?

Binary operators perform actions with two operands. In a complex expression, (two or more operands) the order of evaluation depends on precedence rules. Unary operators are arithmetic operators that perform an action on a single operand.

What is the operator between the operands is called?

An operator performs a function on one, two, or three operands. An operator that requires one operand is called a unary operator. For example, ++ is a unary operator that increments the value of its operand by 1. An operator that requires two operands is a binary operator. .


2 Answers

You can use dis here to see how the expression was actually evaluated:

In [29]: def func():
   ....:     return 5 -+-+-+ 2
   ....: 

In [30]: import dis

In [31]: dis.dis(func)
  2           0 LOAD_CONST               1 (5)
              3 LOAD_CONST               2 (2)
              6 UNARY_POSITIVE      
              7 UNARY_NEGATIVE      
              8 UNARY_POSITIVE      
              9 UNARY_NEGATIVE      
             10 UNARY_POSITIVE      
             11 BINARY_SUBTRACT     
             12 RETURN_VALUE        

So that expression is equivalent to this:

In [32]: 5 - (+(-(+(-(+(2))))))
Out[32]: 3
like image 156
Ashwini Chaudhary Avatar answered Sep 30 '22 19:09

Ashwini Chaudhary


This is just equal to

5 - (+(-(+(-(+2)))))

where all the + and - beyond the first are unary operators. For numbers, + returns the operand unchanged. But, its meaning can be overridden using the __pos__ special method on your own classes.

It's useless obfuscation to do this with numbers, but it may be useful (if incredibly confusing) if you are using class instances with custom __neg__ and/or __pos__ operations.


You can abuse this to get C-like pre-increment -- and ++ operators. Don't ever actually do this.

class IncrementableInteger(object):
    def __init__(self, val=0):
        self.val = val
    def __pos__(self):
        class PlusOne:
            def __pos__(_self):
                self.val += 1
        return PlusOne()
    def __neg__(self):
        class MinusOne:
            def __neg__(_self):
                self.val -= 1
        return MinusOne()
    def __str__(self):
        return str(self.val)
    def __repr__(self):
        return repr(self.val)

Example:

>>> IncrementableInteger(4)
4
>>> v=_
>>> ++v
>>> v
5
like image 21
nneonneo Avatar answered Sep 30 '22 19:09

nneonneo