Ternary plus

  • Thread starter Martin Drautzburg
  • Start date
M

Martin Drautzburg

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 "+"
 
R

Robert Kern

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 "+"

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
 
S

Steven D'Aprano

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 "+"

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:
.... def __add__(self, other, foo=None):
.... print self, other, foo
.... return 1
....<__main__.F instance at 0xb7f06d8c> 3 4
1



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

*wink*
 
C

Carl Banks

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 "+"

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
 
M

Martin Drautzburg

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.
 
G

Gabriel Genellina

En Tue, 09 Feb 2010 15:47:43 -0300, Martin Drautzburg
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.
 
M

Mark Dickinson

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.
Decimal('1.02E+4')
"""
return a.__add__(b, context=self)
 
M

Mark Dickinson

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,176
Messages
2,570,947
Members
47,501
Latest member
Ledmyplace

Latest Threads

Top