增加循环内范围的上限并不会使其永远运行

Pin*_*u21 10 python variables for-loop

我是使用Python 3.7.1的计算机科学入门学生。

我们正在与“ Additorials”合作,您在其中取一个数字并获取该数字加上该数字之前的每个数字的总和。即:对于数字10-- 10 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 = 55

我必须编写一个程序来执行此操作。但是,我这样做的方式不起作用,但确实可行。

def bigAdd(n):
    for i in range(0,n):
        n+=i
    return n
Run Code Online (Sandbox Code Playgroud)

例如,如果我输入数字10,则返回55

但为什么?

如果此循环的上限为n,并且不断增加i,那么是否应该因为不断提高其上限而永远运行呢?为什么它返回任何答案,更不用说正确的答案了?

tob*_*s_k 20

您要添加 n,最初是10(或您使用的上限)。因此,您的结果确实是10 (the initial value) + 0 + 1 + ... + 9 (from the range)

话虽如此,我还是电子书籍使用的初始值n,而是得到sumrange(1, n+1),因为这是很多更清晰。

>>> sum(range(1, n+1))
55
Run Code Online (Sandbox Code Playgroud)

或者,如果您想炫耀:

>>> n*(n+1)//2
55
Run Code Online (Sandbox Code Playgroud)

关于您的第二个问题:1不,第一次进入循环range(0, n)时,只会评估一次,而for不是在每次迭代中。您可以认为这段代码大致相当于2

r = range(0, n) # [0, 1, 2, 3, ..., n-2, n-1]
for i in r:
    n+=i
Run Code Online (Sandbox Code Playgroud)

特别是,Python的for ... in ...循环不是for (initialization; condition; action)Java,C和其他语言中已知的“典型” 循环,而是更类似于“ for-each”循环,它遍历给定集合,生成器或其他可迭代类型的每个元素。

1)我现在意识到,这实际上是您的实际问题...

2)是的,a range不会创建列表,而是一种特殊的可迭代列表,这就是为什么我说“大致”。


Car*_*ate 14

range(0,n)进入循环之前将被评估一次。

这不像for来自其他语言的具有不断检查条件的典型循环。range返回产生数字的范围对象,并且在创建范围对象时设置上限。更改n不会影响已经构造的范围对象。


Ful*_*Guy 5

这是因为int值是不可变的,并且range只在开始时捕获该特定实例一次。

在循环内部时,最初n指向该值的变量在10每次添加一些数字时都会重新指向一个 int实例。并且因为range只计算一次它保留对原始int实例的引用10

函数在开头int引用的实例range在 for 循环中根本没有发生变化,仍然指向 的int实例值10

这就是循环完成的原因,即使n现在每次都指向不同的数字。

试试这个例子片段,你可以证明这一点:

def bigAdd(n):
    for i in range(0,n):
        #temp captures the int before the addition
        temp = n
        n+=i
        print(temp is n)
    return n
Run Code Online (Sandbox Code Playgroud)

输出是:

bigAdd(10)
True
False
False
False
False
False
False
False
False
False
Out[8]: 55
Run Code Online (Sandbox Code Playgroud)

第一行打印True10 + 010这样两个是相同的实例。

  • 我相信这是更正确的答案,特别是参考问题中的OP背景。 (3认同)
  • `range(start, stop)` 是一个构造函数。`stop` 被设置为 n 的值。然后“stop”保持它自己的值——它指向“10”,而不是n。 (3认同)
  • 我认为这个答案有些误导,结论是不正确的。正如 @Carcigenicate 的回答中所指出的,修改“n”并不重要的原因是因为“range”被评估一次。使用可变值会产生相同的效果。`x = [n]; for i in range(0, x[0]): x[0]+= i` 也将完成。 (2认同)
  • 第一个语句打印 true 的原因并不是因为 `temp` 和 `n` 彼此指向对方,第一个语句打印 true 是因为不可变对象 `10` 是在内存中创建的。系统会记住这个不可变的对象,因此现在只要有某个值等于“10”,它就会指向该缓存内存。 (2认同)