Python中的迭代器(循环变量)

3
为了练习和更好地理解for循环,我设计了一个计算给定数字阶乘的函数。除了迭代器(循环变量)的作用,我基本上都明白了。
以下是我设计的函数:
def main():
    print("This program computes the factorial of a number!")
    n = eval(input("Enter a whole number: "))
    fact = 1
    for factor in range(n, 1, -1):
        fact = fact * factor
    print("The factorial of {} is {}!".format(n, fact))
main()

当我运行计算6的阶乘的程序时,函数会输出:6的阶乘是720! 我想了解程序用户提供的输入变量n在迭代器(循环变量)factor中起到什么作用和关系?
为了测试这一点,我删除了迭代器(循环变量)factor并将其替换为输入变量n
def main():
    print("This program computes the factorial of a number!")
    n = eval(input("Enter a whole number: "))
    fact = 1
    for n in range(n, 1, -1):
        fact = fact * n
    print("The factorial of {} is {}!".format(n, fact))
main()

当我使用与先前代码相同的阶乘数字6运行程序时,函数会打印: 2的阶乘是720! 当我要求Python计算相同的阶乘数时,为什么会得到两个不同的答案。显然,后面的代码有些问题,我认为这与输入变量n和迭代器(循环变量)factor之间的关系有关。

1
你在第二个版本中使用变量 n 作为循环变量,覆盖了原始变量 n - bereal
  1. 有一个 math.factorial 函数;
  2. n 正在被 for 循环覆盖。
- Mark R.
1
与问题无关,但很重要:为了Guido的缘故,请不要使用evalint(input(...))就足够了。 - bereal
@bereal:确实。旧的2.x input() 被废弃是有原因的。 - Kevin
感谢 bereal、Mark 和 Kevin 的澄清。很有道理。听说使用 eval 可能会带来潜在的后果。谢谢提醒。 - user4581398
4个回答

3

从您的工作代码开始:

def main():
    print("This program computes the factorial of a number!")
    n = eval(input("Enter a whole number: "))
    fact = 1
    for factor in range(n, 1, -1):
        fact = fact * factor
    print("The factorial of {} is {}!".format(n, fact))
main()

添加打印语句(专业提示:这是一种非常有用的调试技巧):

def main():
    print("This program computes the factorial of a number!")
    n = eval(input("Enter a whole number: "))
    fact = 1
    for factor in range(n, 1, -1):
        print(factor)  # Add this line
        fact = fact * factor
    print("The factorial of {} is {}!".format(n, fact))
main()

你应该看到如下输出:
6
5
4
3
2
The factorial of 6 is 720!

正如您所看到的,factor变量在每次循环中都会改变。它取得了您指定的range()中每个连续的值。
当您将循环变量更改为n时,它被这些值覆盖。

那么迭代器(循环变量)有点保护原始变量“n”的值,对吗? - user4581398
该值本身不需要“保护”。您只需要小心不要覆盖它。将循环视为运行 factor = 6... factor = 5,直到2。如果您使用 n 而不是 factor,则 n 的旧值将被删除。 - Kevin
非常有道理。感谢你的帮助,Kevin。祝一切顺利! - user4581398
还请看一下我的回答。我在这里重申一遍。你现在是用当前范围range(n, 1, -1)从n到2,将其改为range(1, n+1, 1),它将允许你从1到6,并得到正确的输出6的阶乘是720 - RPBruiser
@RPBruiser:将从n到2的值相乘,与从1到n相乘得到的答案相同。乘法是可交换的,乘以1不会改变任何东西。OP的第一个示例已经产生了正确的输出。 - Kevin
@Kevin,我明白这一点,我并不是在说他的数学有问题,而是因为n被覆盖了,所以输出结果是The factorial of 2 is 720,因为n从6变成了2,这就是为什么它会说阶乘是2,但是如果他从1到6进行循环,它将会得到正确的输出结果The factorial of 6 is 720,因为n被覆盖为1开始,并且只会一直循环到所需的n值。我并不是在说他的数学有问题,我只是想说他的range()写法是导致错误的原因。 - RPBruiser

0
在你的第二个程序中,当函数运行到打印语句时,n已经被for循环改变了。因此,虽然n在循环内部按照你的预期发生变化,但是当你打印n时,它已经被循环覆盖了。

感谢您的反馈,Geoffrey。非常感激。 - user4581398

0
  1. 覆盖变量:

当用户输入的值被定义在变量 n 中时,在第二个例子中,变量 n 再次被定义在 for 循环中。因此,变量 n 被覆盖。 检查变量 n 的标识。

例如:

>>> n = 6
>>> id(n)
160708724
>>> n = 2
>>> id(n)
160708772
>>> 
  1. 从键盘输入数值时,使用异常处理来进行类型转换。

例如,当代码需要从键盘获取数字时。

>>> try:
...    n = int(raw_input("Enter number:"))
... except ValueError:
...    print "Enter only number value."
... 
Enter number:99
>>> n
99
>>> type(n)
<type 'int'>
>>> try:
...    n = int(raw_input("Enter number:"))
... except ValueError:
...    print "Enter only number value."
... 
Enter number:test
Enter only number value.
>>> 

与您的第二个示例相关:我只打印n的值

代码:

def factorialGenerator():
    print("This program computes the factorial of a number!")
    while True:
        try:
            n = int(raw_input("Enter a whole number: "))
            break
        except ValueError:
            print "Enter only digit."

    print "\nUser enter value %d and its id %s\n"%(n, id(n))

    fact = 1
    for n in range(n, 1, -1):
        print "In for loop value %d and its id %s"%(n, id(n))
        fact = fact * n

    print("\nThe factorial of {} is {}!".format(n, fact))


if __name__=="__main__":
    factorialGenerator()

输出:

This program computes the factorial of a number!
Enter a whole number: r
Enter only digit.
Enter a whole number: 6

User enter value 6 and its id 142415988

In for loop value 6 and its id 142415988
In for loop value 5 and its id 142416000
In for loop value 4 and its id 142416012
In for loop value 3 and its id 142416024
In for loop value 2 and its id 142416036

The factorial of 2 is 720!

0

尝试:

def main():
    print("This program computes the factorial of a number!")
    n = eval(input("Enter a whole number: "))
    fact = 1
    for n in range(1, n+1, 1):
        fact = fact * n
    print("The factorial of {} is {}!".format(n, fact))
main()

你的问题在于将n在6处覆盖为2,而使用新范围时,它会从一开始就被覆盖,直到达到所需的n值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接