Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Ternary plus

0 views
Skip to first unread message

Martin Drautzburg

unread,
Feb 8, 2010, 3:59:18 PM2/8/10
to
Just for the hell of it ...

I can easily define __plus__() with three parameters. If the last one is
optional the + operation works as expected. Is there a way to pass the
third argument to "+"

Robert Kern

unread,
Feb 8, 2010, 4:28:54 PM2/8/10
to pytho...@python.org

No.

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco

Steven D'Aprano

unread,
Feb 8, 2010, 8:49:39 PM2/8/10
to

How do you give three operands to a binary operator? Binary operators
only have two sides, a left and a right, so you can only fit two operands
around them.

Mathematicians solve this problem by using functions:

add(a, b, c, d)

In Python, you can do this:

>>> class F:
... def __add__(self, other, foo=None):
... print self, other, foo
... return 1
...
>>>
>>> F() + 3
<__main__.F instance at 0xb7f06f4c> 3 None
1
>>> F().__add__(3, 4)
<__main__.F instance at 0xb7f06d8c> 3 4
1

but if you do, people will laugh and point at you in the street.

*wink*


--
Steven

Carl Banks

unread,
Feb 8, 2010, 9:46:05 PM2/8/10
to
On Feb 8, 12:59 pm, Martin Drautzburg <Martin.Drautzb...@web.de>
wrote:

If, for some reason, you wanted to define a type for which it makes
sense to "add" three objects, but not two, you can get the effect you
want, kind of.

(a + b + c) is useful
(a + b) is meaningless

You can have __add__ return a closure for the first addition, then
perform the operation on the second one. Example (untested):

class Closure(object):
def __init__(self,t1,t2):
self.t1 = t1
self.t2 = t2
def __add__(self,t3):
# whole operation peformed here
return self.t1 + self.t2 + t3

class MySpecialInt(int):
def __add__(self,other):
return Closure(self,other)


I wouldn't recommend it. Just use a function call with three
arguments.


Carl Banks

Martin Drautzburg

unread,
Feb 9, 2010, 1:47:43 PM2/9/10
to
Carl Banks wrote:


> You can have __add__ return a closure for the first addition, then
> perform the operation on the second one. Example (untested):
>
> class Closure(object):
> def __init__(self,t1,t2):
> self.t1 = t1
> self.t2 = t2
> def __add__(self,t3):
> # whole operation peformed here
> return self.t1 + self.t2 + t3
>
> class MySpecialInt(int):
> def __add__(self,other):
> return Closure(self,other)
>
>
> I wouldn't recommend it. Just use a function call with three
> arguments.

That's way cool.

<Flash of insight> Of course! - CURRYING!! If you can return closures
you can do everything with just single-parameter functions.</Flash of
insight>

BTW I am not really trying to add three objects, I wanted a third object
which controls the way the addition is done. Sort of like "/" and "//"
which are two different ways of doing division.

Anyways: thanks a lot.

Gabriel Genellina

unread,
Feb 9, 2010, 6:59:16 PM2/9/10
to pytho...@python.org
En Tue, 09 Feb 2010 15:47:43 -0300, Martin Drautzburg
<Martin.D...@web.de> escribi�:

> Carl Banks wrote:
>
>> You can have __add__ return a closure for the first addition, then
>> perform the operation on the second one. Example (untested):
>>
>

> That's way cool.
>
> <Flash of insight> Of course! - CURRYING!! If you can return closures
> you can do everything with just single-parameter functions.</Flash of
> insight>
>
> BTW I am not really trying to add three objects, I wanted a third object
> which controls the way the addition is done. Sort of like "/" and "//"
> which are two different ways of doing division.

See http://code.activestate.com/recipes/384122/ for another cool hack that
may help with that.

--
Gabriel Genellina

Mark Dickinson

unread,
Feb 10, 2010, 3:31:43 AM2/10/10
to
On Feb 9, 6:47 pm, Martin Drautzburg <Martin.Drautzb...@web.de> wrote:
> BTW I am not really trying to add three objects, I wanted a third object
> which controls the way the addition is done. Sort of like "/" and "//"
> which are two different ways of doing division.

That seems like a reasonable use case for a third parameter to
__add__, though as others have pointed out the only way to pass the
third argument is to call __add__ explicitly. Here's an extract from
the decimal module:

class Decimal(object):

...

def __add__(self, other, context=None):
other = _convert_other(other)
if other is NotImplemented:
return other

if context is None:
context = getcontext()

<add 'self' and 'other' in context 'context'>

...

And here's how it's used in the decimal.Context module:

class Context(object):

...

def add(self, a, b):
"""Return the sum of the two operands.

>>> ExtendedContext.add(Decimal('12'), Decimal('7.00'))
Decimal('19.00')
>>> ExtendedContext.add(Decimal('1E+2'), Decimal('1.01E+4'))
Decimal('1.02E+4')
"""
return a.__add__(b, context=self)

--
Mark

Mark Dickinson

unread,
Feb 10, 2010, 3:42:05 AM2/10/10
to
On Feb 10, 8:31 am, Mark Dickinson <dicki...@gmail.com> wrote:
> And here's how it's used in the decimal.Context module:

Aargh! decimal.Context *class*, not module.

And it occurs to me that it would have been cleaner to have
Decimal.__add__ call Context.add rather than the other way around.
Then Decimal.__add__ could have stayed a two-argument function, as
<deity of your choice> intended. Oh well.

--
Mark

0 new messages