问题 Python的__add__和__concat__有什么区别?


Python的标准运算符列表包括两者 __add__(a, b) 和 __concat__(a, b)。它们通常都被调用 a + b。我的问题是,它们之间有什么区别?是否存在使用一个而不是另一个的情况?你有什么理由在一个对象上定义它们吗?

这是 文件 我找到了提到的方法。

编辑:添加到古怪是这个 文件

最后,序列类型应该通过定义方法来实现加法(意味着连接)和乘法(意味着重复) __add__()__radd__()__iadd__()__mul__()__rmul__() 和 __imul__() 如下面所描述的;他们不应该定义 __coerce__() 或其他数字运算符。


3879
2018-06-18 19:51


起源

根据您链接到一个的文档是数字,一个是序列 - Craicerjack
注意 __concat__ 不是 “神奇的方法” 喜欢 __add__ 是: docs.python.org/2/reference/datamodel.html - jonrsharpe
是 除了名字之外还有区别吗? - user2864740
@jonrsharpe - 是什么让你说一个是“魔法”而另一个不是?这甚至是一个官方术语 - 我认为这只是一个人们组成的术语,因为在口头对话中提到“魔术<方法>”这个词比“下划线下划线<方法>下划线下划线”要容易得多。另外,看一下你链接到的文档,我发现了一个让它更令人困惑的引用。我编辑了我的问题以包含它。 - ArtOfWarfare
@ArtOfWarfare 神奇的方法 是指 __foo__ 双下划线 - 双方法 实现实际的类行为 - 例如 a + b 决心 a.__add__(b)。为什么这句话让你感到困惑?它只是告诉你 __add__ 两个序列通常应该端到端地连接它们。 - jonrsharpe


答案:


如果你检查的来源 operator 模块(CONCAT),您将找到这些函数的这些定义:

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

所以除了那之外没有任何区别 concat 实际上需要序列类型。这两个功能都使用了 + 运算符哪个效果取决于您添加的类型。

一般来说,使用 operator 模 在大多数时候都不是那么有用。当您需要传递执行操作的函数(例如,功能函数)时,主要使用该模块 mapfilter, 要么 reduce。但通常,你可以使用 + 直接操作员。

至于下划线功能(__add__ 和 __concat__), 这些是 只是别名

__add__ = add
__concat__ = concat

但那些当然与之无关 特殊方法 用于为自定义类型的运算符重载。它们是与那些特殊方法名称相同的函数,可能使它们看起来相似。请注意,没有特别的 __concat__ 但是对象的方法。

实施 __add__ 但是,在自定义类型上将影响操作员模块功能的工作方式,例如:

>>> 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)

如你看到的, operator.add 将使用特殊方法的实现 Example.__add__;但原因就是执行 operator.add 只是使用了 + 运算符(该行为由特殊行为明确定义 __add__ 方法)。


10
2018-06-18 19:55



好, operator 模块对于将运算符传递给有用 reduce() - fferri
@mescalinum这就是我写的: “当您需要传递执行操作的函数时,主要使用该模块。” - poke
好。我只想提一下 reduce() 因为函数式编程太酷了:) - fferri
@mescalinum我添加了一些功能示例,仅供您使用;) - poke


  • operator.__add__(a, b):回归 a + b,为 a 和 b  数字 *。
  • operator.__concat__(a, b):回归 a + b 对于 a 和 b  序列

有什么不同?

例如,您不能连接整数:

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

  • 其实 __add__(a, b) 就是这样 a + b因此它也适用于序列。

3
2018-06-18 19:54





按照文档,

operator.__add__(a, b) 返回a + b,表示a和b数字。

operator.__concat__(a, b) 为a和b序列返回a + b。

operator .__ add __(a,b):

它只会尝试执行 a + b 并给出结果。

例如。 

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

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

operator .__ concat __(a,b):

在这里,它将检查是否 a 有属性 __getitem__。如果它没有 __getitem__ 属性它引发异常,否则尝试执行 a + b

例如。

在对数字执行此操作时,它将引发异常。

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

在两个字符串上执行时,它执行字符串连接。

operator.__concat__('a','b')
'ab'

0
2018-06-18 19:59



这个行为 其实 区别/限制? operator.add("a","b") 产生预期的结果("a"+"b"=>"ab")并且文档说两者都“返回a + b”。 - user2864740
注意OP正在谈论 operator 模块,而不是特殊方法。另请注意,没有特别之处 __concat__ 方法。 - poke
更新了ans。 - Rahul Gupta