Python增加了赋值问题

nos*_*nos 15 python arrays numbers numpy complex-numbers

我遇到了有关python增强任务的有趣内容 +=

似乎是自动数据类型转换并不总是a += b如果a是一个'更简单'的数据类型,而a = a + b似乎总是工作

转换完成的情况

a = 1
b = 1j

a = 1
b = 0.5
Run Code Online (Sandbox Code Playgroud)

没有进行转换的情况

from numpy import array
a = array([0, 0 ,0])
b = array([0, 0, 1j])
Run Code Online (Sandbox Code Playgroud)

之后a += b,a仍然是整数矩阵,而不是复数矩阵

我以前认为a += b是相同a = a + b的,它们在底层实现中的区别是什么?

kin*_*all 15

对于+运算符,Python定义了一个对象可以实现的三种"特殊"方法:

  • __add__:添加两个项目(+运算符).当你这样做时a + b,__add__方法ab作为参数调用.
  • __radd__:反映添加; 因为a + b,作为实例调用__radd__方法.这仅在不知道如何进行添加且两个对象是不同类型时使用.baa
  • __iadd__:就地添加; 用于a += b将结果分配回左变量的位置.这是单独提供的,因为它可能以更有效的方式实现它.例如,if a是一个列表,那么a += b就是一样a.extend(b).但是,如果c = a + b您必须a在扩展之前复制,因为a在这种情况下不需要修改.请注意,如果您没有实现,__iadd__那么Python将只调用它__add__.

因此,由于这些不同的操作是使用单独的方法实现的,因此实现它们是可能的(但通常是不好的做法),因此它们完全不同,或者在这种情况下,可能只是略有不同的事情.

其他人推断出您正在使用NumPy并解释其行为.但是,您询问了底层实现.希望你现在明白为什么有时候这种情况a += b不一样了a = a + b.顺便说一下,也可以为其他操作实现类似的三个方法.请参阅此页面以获取所有受支持的就地方法的列表.


Sin*_*ion 8

如果arraynumpy.array(您实际上没有指定),那么发生的问题是因为这些数组无法更改其类型.在没有类型说明符的情况下创建数组时,它会猜测一个类型.如果您然后尝试执行该类型不支持的操作(例如将其添加到具有更大域的类型,如复杂的),numpy知道执行计算,但它也知道结果只能存储在类型中拥有更大的域名.它抱怨(在我的机器上,无论如何,我第一次做这样的任务)结果不合适.当你进行常规添加时,必须在任何情况下都要创建一个新数组,numpy会给它提供正确的类型.

>>> a=numpy.array([1])
>>> a.dtype
dtype('int32')
>>> b=numpy.array([1+1j])
>>> b.dtype
dtype('complex128')
>>> a+b
array([ 2.+1.j])
>>> (a+b).dtype
dtype('complex128')
>>> a+=b
>>> a
array([2])
>>> a.dtype
dtype('int32')
>>> 
Run Code Online (Sandbox Code Playgroud)