Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python i=i+;1和i+;=a'中有1个;对于';环_Python_Loops_Numpy_Operators - Fatal编程技术网

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]