2010-07-09 41 views
46

从我所知甚少的情况来看,+ op列表只需要第二个操作数是可迭代的,这个“哈”显然就是。如果x是列表,为什么x + =“ha”有效,而x = x +“ha”会抛出异常?

在代码:

>>> x = [] 
>>> x += "ha" 
>>> x 
['h', 'a'] 
>>> x = x + "ha" 
Traceback (most recent call last): 
File "<stdin>", line 1, in <module> 
TypeError: can only concatenate list (not "str") to list 
+1

我“同意”您的问题;这对于我来说是反对运营商重载的一个很好的理由。 – u0b34a0f6ae 2010-07-09 21:35:50

+0

在编辑之后删除了我的答案 - 看起来你对不支持列表和迭代器之间的原因感到疑惑 - 我的错误。 除了说,“是的,为什么不呢?”,我没有答案。 – 2010-07-09 21:40:16

+3

这是一个*重大*破损。更一般地说,任何为相同外观的操作员定义不同行为的语言或库应该被视为用户敌对的。没有人会使用'+'来表示字符串连接:该操作不可交换! – 2010-07-09 21:40:20

回答

33

使用+=与列表就像调用extend,不+

  • 您可以使用迭代器调用extend
  • 您只能使用+与另一个列表。

我只能猜测为什么做出这个决定,但我想它是出于性能原因。调用+会导致创建新对象并复制所有项目,而在某些情况下,extend可以使用现有列表对象中的可用空间来保存副本。

此决定的另一个副作用是,如果您编写x += y其他引用列表将看到更改,但如果您使用x = x + y那么他们不会。下面展示了这种:

 
>>> x = ['a','b'] 
>>> y = ['c', d'] 
>>> z = x 
>>> x += y 
>>> z 
['a', 'b', 'c', 'd'] 

>>> x = ['a','b'] 
>>> y = ['c', d'] 
>>> z = x 
>>> x = x + y 
>>> z 
['a', 'b'] 

参考

Python source code for list

+=的源代码:

 
static PyObject * 
list_inplace_concat(PyListObject *self, PyObject *other) 
{ 
    PyObject *result; 

    result = listextend(self, other); 
    if (result == NULL) 
     return result; 
    Py_DECREF(result); 
    Py_INCREF(self); 
    return (PyObject *)self; 
} 

源代码+

 
static PyObject * 
list_concat(PyListObject *a, PyObject *bb) 
{ 
    Py_ssize_t size; 
    Py_ssize_t i; 
    PyObject **src, **dest; 
    PyListObject *np; 
    if (!PyList_Check(bb)) { 
     PyErr_Format(PyExc_TypeError, 
        "can only concatenate list (not \"%.200s\") to list", 
        bb->ob_type->tp_name); 
     return NULL; 
    } 

    // etc ... 
+20

我想这里真正的问题是,“为什么这样的不一致?” – doublep 2010-07-09 21:40:18

+0

我在这个答案上走-1的边缘,因为它根本不回答问题(请参阅@ doublep的评论)。 – 2010-07-09 21:41:46

+5

我并不认为这个问题是对设计的批评。第一步是了解不一致性是如何实现的,这里我们可以提供帮助。你提出的更大的问题完全超出了SO的范围,如果你问我:) – 2010-07-09 21:55:41

8

你向后想着它。你问为什么x = x + 'ha'抛出一个例外,因为x += 'ha'的作品。真的,问题是为什么x += 'ha'工作。

大家都同意(我希望)'abc' + 'ha'[1, 2, 3] + ['h', 'a']应该工作。在这些情况下,重载+=进行就地修改似乎是合理的。

语言设计者决定[1, 2, 3] + 'ha'不应该,因为你在混合不同的类型。这似乎也是合理的。

所以问题是为什么他们决定允许x += 'ha'的情况下混合不同的类型。在这种情况下,我想有几个方面的原因:

  • 这是一个方便的速记
  • 很明显发生了什么(你追加每个项目在迭代到x

一般,Python试图让你做你想做的事情,但是在有歧义的地方,它往往会迫使你明确表达。

+2

另一个尝试性-1:对我来说,显而易见的是,对于任何'x'和'y','x + = y'被定义为'x = x + y'。立刻就清楚你避免回答这个问题。 ;) – 2010-07-09 21:43:18

+6

我认为这里的重点是它*不明显,因此是问题。在定义'+ ='和'+'的大多数其他编程语言中,通常将'x + = y'定义为与'x = x + y'完全相同。事实上,通常一个是另一个的别名。 – 2010-07-09 21:55:48

+0

很明显,如果你尝试它,很清楚会发生什么。并不是说,如果你不期待它的工作,你会失望的时候。 – 2010-07-09 22:04:00

相关问题