__iadd__ with 2 args?

Steven D'Aprano steve+comp.lang.python at pearwood.info
Sat Mar 21 01:37:35 EDT 2015


On Sat, 21 Mar 2015 08:25 am, Neal Becker wrote:

> I can write a member
> 
> F.__iadd__ (self, *args)
> 
> and then call it with 2 args:
> 
> f = F()
> f.__iadd__ (a, b)
> 
> And then args is:
> (a, b)


If you find yourself explicitly calling dunder methods like __iadd__, that's
a sign you are trespassing in the interpreter's area. With a few documented
exceptions, anything with leading and trailing double underscores is
reserved for the interpreter's use.

But having said that, dunder methods are ordinary methods. You can define
them any way you like:

def __iadd__(self, x, y, z, foo="Hello world", *args, **kw):
    pass

and then call the method directly with the arguments you want. But what you
CANNOT do is change the way the Python interpreter uses the dunder method.

Python takes statements of the form:

    x += expression

and calls type(x).__iadd__(x, expression). There is no way to force Python
to treat expression as multiple arguments, it will be passed to your method
as a tuple.

If you wish to write code like this:

    x += a, b, c


then your __iadd__ method needs to look something like this:

def __iadd__(self, arg):
    if not isinstance(arg, tuple):
        arg = (arg,)
    ...


> But it seems impossible to spell this as
> 
> f += a, b
> 
> That, instead, results in
> 
> args = ((a, b),)

Correct. You use *args to collect multiple arguments, but Python only passes
a single argument, the tuple (a,b).


> So should I just abandon the idea that += could be used this way?

Yes, sorry.

 

-- 
Steven




More information about the Python-list mailing list