Python i=i+;1和i+;=a'中有1个;对于';环
今天我发现了一件奇怪的事情,想知道是否有人能解释一下这里的区别Python i=i+;1和i+;=a'中有1个;对于';环,python,loops,numpy,operators,Python,Loops,Numpy,Operators,今天我发现了一件奇怪的事情,想知道是否有人能解释一下这里的区别 import numpy as np A = np.arange(12).reshape(4,3) for a in A: a = a + 1 B = np.arange(12).reshape(4,3) for b in B: b += 1 在为循环运行每个之后,A没有改变,但是B在每个元素中添加了一个。实际上,我使用B版本在for循环中写入初始化的NumPy数组。区别在于一个修改数据结构本身(就地操作)B+
import numpy as np
A = np.arange(12).reshape(4,3)
for a in A:
a = a + 1
B = np.arange(12).reshape(4,3)
for b in B:
b += 1
在为循环运行每个
之后,A
没有改变,但是B
在每个元素中添加了一个。实际上,我使用B
版本在for
循环中写入初始化的NumPy数组。区别在于一个修改数据结构本身(就地操作)B+=1
,而另一个只重新分配变量a=a+1
为了完整起见:
x+=y
并非总是执行就地操作,至少有三种例外情况:
- 如果
x
没有实现\uuuu-iadd\uuuu
方法,那么x+=y
语句只是x=x+y
的简写。如果x
类似于int
,就会出现这种情况
- 如果
返回未实现
,Python将返回x=x+y
\uuuu iadd\uuu
方法在理论上可能无法实施。但是那样做真的很奇怪
碰巧的是,您的b
s是numpy.ndarray
s,它实现了\uuu iadd\uuuu
并返回自身,因此您的第二个循环修改了原来的数组
有关这方面的更多信息,请参阅
调用这些[.*.
]方法来实现增广算术赋值(+=
,-=
,*=
,@=
,/=
,/=
,%=
,**
,
,
,
,
)。这些方法应该尝试就地执行操作(修改self)并返回结果(可能是,但不一定是self)。如果未定义特定的方法,则扩充赋值将返回到正常方法。例如,如果x是具有方法的类的实例,x+=y
相当于x=x.\uu iadd\uu(y)
。否则,将考虑x.\uu添加\uuu(y)
和y.\uu radd\uuuu(x)
,就像计算x+y
一样。在某些情况下,扩充赋值可能会导致意外错误(请参阅),但这种行为实际上是数据模型的一部分
在第一个示例中,您正在重新分配变量a
,而在第二个示例中,您正在使用+=
运算符修改数据
请参阅关于以下内容的章节:
像x+=1
这样的增广赋值表达式可以重写为x=x+1
,以获得类似但不完全相同的效果。在增强版本中,x只计算一次此外,如果可能,实际操作将就地执行,这意味着不创建新对象并将其分配给目标,而是修改旧对象
+=
操作员呼叫。此函数在适当的位置进行更改,仅在执行后,结果才会设置回您正在“应用”上的+=
对象
另一方面,获取参数并返回它们的和(不修改它们)。短格式(a+=1
)可以选择修改a
,而不是创建表示和的新对象并将其重新绑定回相同的名称(a=a+1
)。因此,短格式(a+=1
)与a=a+1
不同,它不一定需要复制a
,因此效率更高
此外,即使它们输出相同的结果,也要注意它们是不同的,因为它们是独立的运算符:+
和+=
正如前面指出的,b+=1
就地更新b
,而a=a+1
计算a+1
,然后为结果指定名称a
(现在a
不再指a
行)
若要正确理解<代码> += 运算符,我们还需要理解可变对象和不可变对象的概念。考虑当我们省略<代码>时会发生什么。整形< /代码>:
C = np.arange(12)
for c in C:
c += 1
print(C) # [ 0 1 2 3 4 5 6 7 8 9 10 11]
我们看到C
没有更新,这意味着C+=1
和C=C+1
是等价的。这是因为现在C
是一个1D数组(C.ndim==1
),所以当迭代C
时,每个整数元素都被拉出并分配给C
现在在Python中,整数是不可变的,这意味着不允许就地更新,有效地将c+=1
转换为c=c+1
,其中c
现在指的是一个新的整数,而不是以任何方式耦合到c
。当您循环经过重塑的数组时,整行(np.ndarray
)一次分配给b
(和a
),它们是可变对象,这意味着您可以随意插入新整数,这在执行a+=1
时发生
应该提到的是,尽管+
和+=
是如上所述的相关关系(通常也是如此),任何类型都可以通过分别定义\uuu add\uuu>和方法来实现它们。首先:循环中的变量a和b引用numpy.ndarray
对象
在第一个循环中,a=a+1
的计算如下:调用numpy.ndarray
的\uuuu添加(self,other)
函数。这将创建一个新对象,因此不会修改a。之后,变量a
被设置为引用结果
在第二个循环中,没有新对象是cre
In [258]: B
Out[258]:
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])
In [259]: for b in B:
...: print(b,'=>',end='')
...: b += 1
...: print(b)
...:
[0 1 2] =>[1 2 3]
[3 4 5] =>[4 5 6]
[6 7 8] =>[7 8 9]
[ 9 10 11] =>[10 11 12]
In [260]: for b in B:
...: print(b,'=>',end='')
...: b[:] = b * 2
[1 2 3] =>[2 4 6]
[4 5 6] =>[ 8 10 12]
[7 8 9] =>[14 16 18]
[10 11 12] =>[20 22 24]