Mar*_*cin 24 python language-design language-implementation python-internals
任何熟悉Python内部(CPython或其他实现)的人都可以解释为什么列表添加需要是同质的:
In [1]: x = [1]
In [2]: x+"foo"
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
C:\Users\Marcin\<ipython-input-2-94cd84126ddc> in <module>()
----> 1 x+"foo"
TypeError: can only concatenate list (not "str") to list
In [3]: x+="foo"
In [4]: x
Out[4]: [1, 'f', 'o', 'o']
Run Code Online (Sandbox Code Playgroud)
为什么x+"foo"以上不会返回与x上述成绩单中的最终值相同的值?
这个问题来自NPE的问题:Python列表+ = iterable的行为是否记录在何处?
更新:我知道不需要异质+=工作(但确实如此),同样,并不要求异质+是错误.这个问题是为什么做出后一种选择.
很难说将序列添加到列表中的结果是不确定的.如果这是一个充分的反对意见,那么防止异质性是有意义的+=.Update2:特别是,python总是将操作符调用委托给左侧操作数,因此没有问题出现"什么是正确的事情"":左手对象总是管理(除非它委托到右边).
更新3:对于任何人认为这是一个设计决定,请解释(a)为什么没有记录; 或(b)如有文件记录.
Update4:"应该[1] + (2, )返回什么?" 它应该返回一个结果值,该值等于x最初[1]紧跟在之后的变量的值x+=(2, ).这个结果定义明确.
Gar*_*tty 11
来自Python的禅宗:
面对模棱两可,拒绝猜测的诱惑.
让我们来看看这里发生了什么:
x + y
Run Code Online (Sandbox Code Playgroud)
这给了我们一个价值,但是它是什么类型的?当我们在现实生活中添加东西时,我们希望类型与输入类型相同,但如果它们是完全不同的呢?那么,在现实世界中,我们拒绝添加1和"a",它没有任何意义.
如果我们有类似的类型怎么办?在现实世界中,我们看一下背景.计算机不能这样做,所以它必须猜测.Python选择左操作数并让它决定.由于缺乏上下文,您的问题就出现了.
说程序员想做["a"] + "bc"- 这可能意味着他们想要"abc"或["a", "b", "c"].目前,解决方案是调用"".join()第一个操作数或list()第二个操作数,这允许程序员做他们想要的事情,并且清晰明确.
你的建议是让Python猜测(通过内置规则来选择给定的操作数),所以程序员可以通过添加来做同样的事情 - 为什么这样更好?它只是意味着错误地获取错误类型更容易,我们必须记住任意规则(左操作数选择类型).相反,我们得到一个错误,因此我们可以为Python提供正确调用所需的信息.
那为什么+=不同呢?好吧,那是因为我们正在为Python提供上下文.通过就地操作,我们告诉Python修改一个值,所以我们知道我们正在处理我们正在修改的值的类型.这是Python需要进行正确调用的上下文,因此我们不需要猜测.
当我谈论猜测时,我在谈论Python猜测程序员的意图.这是Python做了很多事情 - 请参阅3.x中的分部./浮点除法,纠正它在2.x中的整数除法的误差.
这是因为当我们试图划分时,我们隐含地要求浮动划分.Python将此考虑在内,并根据它完成操作.同样,这是关于猜测意图.当我们添加+我们的意图时尚不清楚.当我们使用时+=,它非常清楚.
这些错误报告表明这种设计怪癖是一个错误.
是的,这是预期的行为,是的,它是不一致的.
这已经很久了,Guido说他不会再这样做了(这是他的遗憾名单).但是,我们不会通过更改代码来破坏代码(
list.__iadd__就像工作一样list.extend).
目的是
list.__iadd__完全符合list.extend().也没有必要进行超广泛化list.__add__():这是一个特征,那些不想被类似马丁的例子感到惊讶的人可以通过使用普通+列表来避免它们.
(当然,有些人发现这种行为非常令人惊讶,包括打开该bug报告的开发人员).
(感谢@Mouad找到这些).