15

The list of Python's standard operators includes both __add__(a, b) and __concat__(a, b). Both of them are usually invoked by a + b. My question is, what is the difference between them? Is there a scenario where one would be used rather than the other? Is there any reason you would define both on a single object?

Here's the documentation I found the methods mentioned in.

Edit: Adding to the weirdness is this documentation:

Finally, sequence types should implement addition (meaning concatenation) and multiplication (meaning repetition) by defining the methods __add__(), __radd__(), __iadd__(), __mul__(), __rmul__() and __imul__() described below; they should not define __coerce__() or other numerical operators.

ArtOfWarfare
  • 20,617
  • 19
  • 137
  • 193
  • Well according to the documentation you linked to one is for numbers and one is for sequences – Craicerjack Jun 18 '15 at 19:55
  • 2
    Note that `__concat__` isn't a *"magic method"* like `__add__` is: https://docs.python.org/2/reference/datamodel.html – jonrsharpe Jun 18 '15 at 19:55
  • *Is* there a difference, except for the name? – user2864740 Jun 18 '15 at 19:59
  • @jonrsharpe - What makes you say that one is a "magic method" and the other isn't? Is that even an official term - I thought it was just a term people made up because it's a lot easier to say the words "magic " when referring to them in a verbal conversation than "underscore underscore underscore underscore". Also, looking at the docs you linked to, I found a quote that makes this even more confusing. I edited my question to include it. – ArtOfWarfare Jun 18 '15 at 20:03
  • @ArtOfWarfare *magic method* refers to the `__foo__` double-underscore-both-sides methods that *implement actual class behaviour* - for example `a + b` is resolved to `a.__add__(b)`. Why is that quote confusing you? It's just telling you that `__add__` for two sequences should generally join them end-to-end. – jonrsharpe Jun 18 '15 at 20:05
  • @ArtOfWarfare The “magic methods” are officially called [“special methods”](https://docs.python.org/3/reference/datamodel.html#special-method-names) and refer to methods which you can implement for types to provide built-in functionality for operators and other syntax features. Double-underscore methods in general are otherwise just subject to [name-mangling](http://stackoverflow.com/questions/7456807/python-name-mangling-when-in-doubt-do-what) and as such is sometimes used for private members. – poke Jun 18 '15 at 20:08
  • @jonrsharpe - Okay, so the important part is that `__concat__` isn't actually defined on any objects - that's why you say it isn't a magic method. If you post an answer laying out the fact that my confusion mostly stems from the `operator` module using method names that are identical to the names of magic methods, then I'll accept that. – ArtOfWarfare Jun 18 '15 at 20:11
  • @ArtOfWarfare I expanded a bit more in my answer on the `operator.add` vs. the special method `__add__`, hope it clears everything up :) – poke Jun 18 '15 at 20:17

3 Answers3

13

If you check the source for the operator module (add, concat), you will find these definitions for those functions:

def add(a, b):
    "Same as a + b."
    return a + b

def concat(a, b):
    "Same as a + b, for a and b sequences."
    if not hasattr(a, '__getitem__'):
        msg = "'%s' object can't be concatenated" % type(a).__name__
        raise TypeError(msg)
    return a + b

So there is actually no difference except that concat actually requires a sequence type. Both functions use the + operator which effect depends on the types you add.

In general, using the operator module is not that useful most of the time. The module is mostly used when you need to pass a function that performs an operation, for example to functional functions like map, filter, or reduce. But usually, you can just use the + operator directly.

As for the underscore functions (__add__ and __concat__), these are just aliases:

__add__ = add
__concat__ = concat

But those are of course not related to the special methods used to overload operators for custom types. They are functions that match the same name as those special methods, probably to make them appear similar. Note that there is no special __concat__ method on objects though.

Implementing __add__ on a custom type will however affect how the operator module functions work, for example:

>>> class Example:
        def __init__ (self, x):
            self.x = x
        def __repr__ (self):
            return 'Example({})'.format(self.x)
        def __add__ (self, other):
            return Example(self.x + other.x)

>>> a = Example(2)
>>> b = Example(4)
>>> operator.add(a, b)
Example(6)
>>> a + b
Example(6)

As you can see, operator.add will use the implementation of the special method Example.__add__; but the reason for that is that the implementation of operator.add just uses the + operator (which behavior is explicitely defined by the special __add__ method).

poke
  • 369,085
  • 72
  • 557
  • 602
3
  • operator.__add__(a, b): Return a + b, for a and b numbers *.
  • operator.__concat__(a, b): Return a + b for a and b sequences.

What's the difference?

For example, you can't concatenate integers:

>>> operator.__concat__(2,3)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: 'int' object can't be concatenated

  • actually __add__(a, b) just does a + b, hence it works on sequences too.
fferri
  • 18,285
  • 5
  • 46
  • 95
0

As per docs,

operator.__add__(a, b) Return a + b, for a and b numbers.

operator.__concat__(a, b) Return a + b for a and b sequences.

operator.__add__(a, b):

It will just try to perform a + b and give the result.

Eg.

operator.__add__(1,2)  # performs 1 + 2
3

operator.__add__('a','b') # performs 'a'+'b'
'ab'

operator.__concat__(a, b):

Here, it will check if a has attribute __getitem__. If it does not have __getitem__ attribute it raises an exception otherwise then try to perform a + b.

Eg.

On performing this operations on numbers, it will raise an exception.

operator.__concat__(1,2)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError:'int' object can't be concatenated

When performed on two strings, it perform string concatenation.

operator.__concat__('a','b')
'ab'
Rahul Gupta
  • 46,769
  • 10
  • 112
  • 126
  • Does the behavior *actually* differ/limit? `operator.add("a","b")` produces the expected result (`"a"+"b"=>"ab"`) and the documentation says that the both "Return a + b". – user2864740 Jun 18 '15 at 19:59
  • Note that OP was talking about the `operator` modules, not special methods. Also note that there is no special `__concat__` method. – poke Jun 18 '15 at 20:10