Python中的变量重赋值--本体查询--使用牛顿法
Variable Reassignment in Python-- ontological query -- using Newton Method
我正在使用 Python 阅读 Miller 和 Ranum 关于算法和数据结构的书。他们使用以下示例:
def squareroot(n):
root = n/2
for k in range(20):
root = (1/2)*(root + n / root)
return root
我的问题是,变量 'root' 在 for 循环中被重新赋值,因此随着每次迭代,赋值运算符右侧表达式中 'root' 的值都会发生变化。我不确定我明白这是怎么可能的。
一旦进行了函数调用,for 循环外的 'root' 变量(第 2 行)的计算结果为一个值,然后由表达式中的 'root' 变量引用for 循环块的,允许表达式计算为单个值,该值被重新分配给变量 'root',在 for 循环块中赋值运算符的左侧。在下一次迭代开始时,'root' 不再是 n/2,而是 for 循环中的表达式求得的任何值。在这种情况下,变量 'root' 已被重新分配了一个浮点值,因此不再是它最初定义的值——一个使用 'root' 变量的表达式。
例如,如果我们使用函数调用 squareroot(9),'root' 将在第一次迭代后保持值 3.25,因为 for 循环中的表达式求值为该值。一旦 for 循环中的变量 'root' 被重新分配了一个浮点值,最初定义 'root' 的表达式将被销毁。 'root' 已被重新定义为 3.25。 'root',在for循环中,不再指代一个表达式,而是指一个单一的浮点值。然而,在这个例子中,for 循环中的 'root' 变量在每次迭代后似乎有两个含义:它既是浮点值又是表达式。我不明白怎么会这样。
简短的回答是 Python 不将表达式视为抽象公式;它将其视为要执行的一系列具体计算。每次通过循环,它都会用 root
的当前值执行这些计算,然后使用结果更新 root
的值。查看 Python 执行的实际操作顺序可能会有所帮助,如下所示:
import dis
def squareroot(n):
root = n/2
for k in range(20):
root = 0.5 * (root + n / root)
return root
dis.dis(squareroot)
结果:
2 0 LOAD_FAST 0 (n)
3 LOAD_CONST 1 (2)
6 BINARY_DIVIDE
7 STORE_FAST 1 (root)
3 10 SETUP_LOOP 38 (to 51)
13 LOAD_GLOBAL 0 (range)
16 LOAD_CONST 2 (20)
19 CALL_FUNCTION 1
22 GET_ITER
>> 23 FOR_ITER 24 (to 50)
26 STORE_FAST 2 (k)
4 29 LOAD_CONST 3 (0.5)
32 LOAD_FAST 1 (root)
35 LOAD_FAST 0 (n)
38 LOAD_FAST 1 (root)
41 BINARY_DIVIDE
42 BINARY_ADD
43 BINARY_MULTIPLY
44 STORE_FAST 1 (root)
47 JUMP_ABSOLUTE 23
>> 50 POP_BLOCK
5 >> 51 LOAD_FAST 1 (root)
54 RETURN_VALUE
有趣的部分是以 4
开头的块,它对应于您询问的作业。事情是这样的:
- 将以下内容加载到堆栈上:[0.5,
root
的当前内容,n
的当前内容,root
的当前内容。在第一次迭代期间(n=9),堆栈现在将保存 [0.5, 4.5, 9.0, 4.5].
- 将堆栈中的倒数第二项除以最后一项,并将结果放入堆栈:堆栈现在为 [0.5, 4.5, 2.0]
- 将最后两项添加到堆栈中并将结果放入堆栈中:堆栈现在是 [0.5, 6.5]
- 将堆栈中的最后两项相乘并将结果放入堆栈中:堆栈现在是 [3.25]
- 将堆栈中的最后一项 (3.25) 存储在变量
root
中。
因此,如您所见,表达式仅表示要遵循的一系列步骤。在这些步骤结束时,结果将存储到 root
。然后可以使用 root
.
的新值再次执行这些步骤
我正在使用 Python 阅读 Miller 和 Ranum 关于算法和数据结构的书。他们使用以下示例:
def squareroot(n):
root = n/2
for k in range(20):
root = (1/2)*(root + n / root)
return root
我的问题是,变量 'root' 在 for 循环中被重新赋值,因此随着每次迭代,赋值运算符右侧表达式中 'root' 的值都会发生变化。我不确定我明白这是怎么可能的。
一旦进行了函数调用,for 循环外的 'root' 变量(第 2 行)的计算结果为一个值,然后由表达式中的 'root' 变量引用for 循环块的,允许表达式计算为单个值,该值被重新分配给变量 'root',在 for 循环块中赋值运算符的左侧。在下一次迭代开始时,'root' 不再是 n/2,而是 for 循环中的表达式求得的任何值。在这种情况下,变量 'root' 已被重新分配了一个浮点值,因此不再是它最初定义的值——一个使用 'root' 变量的表达式。
例如,如果我们使用函数调用 squareroot(9),'root' 将在第一次迭代后保持值 3.25,因为 for 循环中的表达式求值为该值。一旦 for 循环中的变量 'root' 被重新分配了一个浮点值,最初定义 'root' 的表达式将被销毁。 'root' 已被重新定义为 3.25。 'root',在for循环中,不再指代一个表达式,而是指一个单一的浮点值。然而,在这个例子中,for 循环中的 'root' 变量在每次迭代后似乎有两个含义:它既是浮点值又是表达式。我不明白怎么会这样。
简短的回答是 Python 不将表达式视为抽象公式;它将其视为要执行的一系列具体计算。每次通过循环,它都会用 root
的当前值执行这些计算,然后使用结果更新 root
的值。查看 Python 执行的实际操作顺序可能会有所帮助,如下所示:
import dis
def squareroot(n):
root = n/2
for k in range(20):
root = 0.5 * (root + n / root)
return root
dis.dis(squareroot)
结果:
2 0 LOAD_FAST 0 (n)
3 LOAD_CONST 1 (2)
6 BINARY_DIVIDE
7 STORE_FAST 1 (root)
3 10 SETUP_LOOP 38 (to 51)
13 LOAD_GLOBAL 0 (range)
16 LOAD_CONST 2 (20)
19 CALL_FUNCTION 1
22 GET_ITER
>> 23 FOR_ITER 24 (to 50)
26 STORE_FAST 2 (k)
4 29 LOAD_CONST 3 (0.5)
32 LOAD_FAST 1 (root)
35 LOAD_FAST 0 (n)
38 LOAD_FAST 1 (root)
41 BINARY_DIVIDE
42 BINARY_ADD
43 BINARY_MULTIPLY
44 STORE_FAST 1 (root)
47 JUMP_ABSOLUTE 23
>> 50 POP_BLOCK
5 >> 51 LOAD_FAST 1 (root)
54 RETURN_VALUE
有趣的部分是以 4
开头的块,它对应于您询问的作业。事情是这样的:
- 将以下内容加载到堆栈上:[0.5,
root
的当前内容,n
的当前内容,root
的当前内容。在第一次迭代期间(n=9),堆栈现在将保存 [0.5, 4.5, 9.0, 4.5]. - 将堆栈中的倒数第二项除以最后一项,并将结果放入堆栈:堆栈现在为 [0.5, 4.5, 2.0]
- 将最后两项添加到堆栈中并将结果放入堆栈中:堆栈现在是 [0.5, 6.5]
- 将堆栈中的最后两项相乘并将结果放入堆栈中:堆栈现在是 [3.25]
- 将堆栈中的最后一项 (3.25) 存储在变量
root
中。
因此,如您所见,表达式仅表示要遵循的一系列步骤。在这些步骤结束时,结果将存储到 root
。然后可以使用 root
.