Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ms-access/4.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:帮助,函数不能产生我想要的_Python_Algorithm_Loops - Fatal编程技术网

Python:帮助,函数不能产生我想要的

Python:帮助,函数不能产生我想要的,python,algorithm,loops,Python,Algorithm,Loops,我试着做一个collatz序列,当我输入初始整数时,它会连续打印出数字,直到它达到1,但是它工作得不太好 def collatz(): try: number = int(input("Please enter a number: ")) except ValueError: collatz() while number != 1: if number%2 == 0: print(number //

我试着做一个collatz序列,当我输入初始整数时,它会连续打印出数字,直到它达到1,但是它工作得不太好

def collatz():
    try:
        number = int(input("Please enter a number: "))
    except ValueError:
        collatz()
    while number != 1:
        if number%2 == 0:
            print(number // 2)
        else:
            print(3 * number + 1)
这是我创建的,它只返回单个计算的值

>>> collatz()
Please enter a number: 45
136
>>> collatz()
Please enter a number: 8
4
我不太明白为什么会发生这种情况,当我想继续计算并一直打印值直到它达到1,它总是会达到1,这是序列的技巧

if number%2 == 0:
    print(number // 2)
else:
    print(3 * number + 1)
实际上,您并没有更改number的值:

if number%2 == 0:
    print(number // 2)
    number = number // 2
else:
    print(3 * number + 1)
    number = 3 * number + 1

您从未将任何新值指定给number,因此while循环永远为True

计算新值,将其分配回数字,然后打印新值:

while number != 1:
    if number % 2 == 0:
        number //= 2
    else:
        number = 3 * number + 1
    print(number)
注意,您不应该使用递归来获取有效的输入;改用while循环。在您的例子中,当递归函数退出并返回时,代码将继续执行编号为unbound的while循环,从而导致UnboundLocal异常

我会把询问号码放在函数之外,也许放在一个新函数中:

def collatz(number):
    while number != 1:
        if number % 2 == 0:
            number //= 2
        else:
            number = 3 * number + 1
        print(number)

def ask_for_number():
    while True:
        try:
            return int(input("Please enter a number: "))
        except ValueError:
            print("That's not a valid number, please try again")

collatz(ask_for_number())
现在,您可以轻松地测试collatz函数,而无需向用户询问数字:

>>> collatz(45)
136
68
34
17
52
26
13
40
20
10
5
16
8
4
2
1

这就是你想要的吗

def collatz(starting_value):
    value = starting_value

    while value != 1:
        value = (3 * value + 1) if value % 2 else (value // 2)
        yield value

if __name__ == '__main__':
    start = int(input("Please enter starting value: "))
    print(list(collatz(start)))
示例运行

请输入起始值:136 [68, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1] 这是怎么回事

这段代码依赖于调用的东西的使用——本质上,它看起来像一个函数,但行为却像一个迭代器。collatz是生成函数,在每次迭代中,它将生成collatz序列中的下一项

当我们直接执行包含此代码的模块时,Python解释器会将其_name__变量设置为“_main__”,使底部的if语句为true

在该if块中,我们提示用户输入从Collatz序列开始的值。我们假设他们输入了一个有效的数字,否则将引发未处理的异常

表达式collatzstart将生成一个我们可以迭代的生成器对象。我们将此对象直接传递到列表中,列表将不断要求该对象反复生成其下一次迭代,直到耗尽为止。我们真的希望Collatz的猜测是真的,否则这个程序可能永远运行下去

Collatz的猜想似乎确实成立,因此最终while条件值!=1变为false,表示生成器对象停止生成值。此时,它将引发StopIteration以表示它没有更多的值,list将返回Collatz术语的完整列表,然后我们将其打印出来

collatz中的yield语句的行为类似于return,只是调用线程“记住”了它的位置——当我们请求序列中的下一个项时,它将从该点开始,使用函数局部变量的最后存储值,即value

垂直打印术语

如果愿意,要垂直打印术语,只需在for循环中迭代生成器,并在新行上打印它生成的每个术语:

if __name__ == '__main__':
    start = int(input("Please enter starting value: "))
    for term in collatz(start):
        print(term)
输出

请输入起始值:136 68 34 17 52 26 13 40 20 10 5. 16 8. 4. 2. 1. 你忘了更新电话号码了 试试这个:

def collatz():
    try:
        number = int(input("Please enter a number: "))
    except ValueError:
        collatz()
    while number != 1:
        if number%2 == 0:
            number = number // 2
            print(number)
        else:
            number = 3 * number + 1
            print(number)
我希望这会有帮助

def collatz():
    try:
        number = int(input("Please enter a number: "))
    except ValueError:
        collatz()
    while number != 1:
        if number %2 ==0:
            number = number // 2
        else:
            number = 3 * number + 1
        print(number) 
打印不会设置数字的实际值

几个问题:

主要一点:你永远不会改变数字的值。 因此,您的代码应该反复打印相同的数字

此外,您可能需要检查非正数

但是,当这个问题得到解决时,我怀疑当您遇到捕获的ValueError时会出现一些不必要的行为。 再次调用相同的函数。完成第二次运行后,代码仍将尝试运行下一行,但失败

例如:

>>>科拉茨 请输入一个数字:foo 请输入一个数字:4 2. 1. 回溯最近一次呼叫上次: 文件,第1行,在 文件,第6行,在collatz中 UnboundLocalError:赋值前引用的局部变量“number” 我将尝试解决所有这些问题:

def collatz: 数字=0 当数字<1时: 尝试: number=intInput请输入一个数字: 除ValueError、NameError外: 通过 而数字!=1: 如果数字%2==0: 数字=数字//2 其他: 数字=3*数字+1 打印号码
您的代码,如发布的一样,将持续打印相同的数字,而不是只打印一次。不要在需要迭代的地方使用递归。Python只支持固定深度的递归,因为它缺乏尾部调用优化。使用类似while-True:try:number=int。。。我不太明白你的意思@chepner@Radanek对于每次错误的输入尝试,您的函数将使用越来越多的内存,在1000次左右失败的极端情况下,实际上会引发异常。while循环允许使用恒定内存进行无限次的错误尝试。我认为这是正确的解决方案,也许是
st删除最后一个收益率值,以避免在结尾处重复打印1。您的评论正如我注意到的一样,哈哈。谢谢你一视同仁地指出这一点。我喜欢这个答案,但我是一个初学者,我看到了很多不寻常的语法。不过,我要找一个答案垂直打印的解决方案。@Radanek没问题。关于不熟悉的语法,我会用更好的解释更新我的帖子,如果你愿意,我会再次ping你,让你知道这是什么时候完成的。是的,我只是选择了这一个作为正确答案,因为我已经学到了我完全理解的新技术和语法。为什么你在处理一个名称错误,而我从来没有得到一个未绑定的本地错误?哦,等等,我确实做了,但我没有明白为什么吗?@Radanek 1我发现了Python 2.7支持的名称错误。输入已尝试解释键入的字符串。@Radanek 2您键入了一个字符串,并捕获结果NameError,从何处开始另一个collatz实例。这个实例可能运行得很好。但在第二个实例返回后,您的第一个实例继续执行while number中的下一行1:. 但在这种情况下,数字根本没有定义。我们尝试了,但是失败了。谢谢,其他人也指出了同样的事情,我不知道初始函数调用的其余部分在递归之后仍然会运行。但是我不明白一件事。如何发生未绑定的本地错误?@Radanek:在您的函数中,只修复while循环。当提示输入数字时,输入无效条目。然后输入正确的数字。不正确的输入会引发ValueError,因此不会执行number=赋值。然后再次调用collatz,输入一个正确的数字,while循环现在完全正确地结束,递归函数调用结束。然后,在调用collatz的同一点返回上一个函数,并输入一个while循环,因为数字从未绑定,导致UnboundLocalError。非常感谢您将其清除。我选择使用yield语句作为正确答案,因为我学会了新语法。这个答案将是我的第二个选择,因为我现在知道,在递归干净地结束之后,初始函数调用的其余部分仍将运行。你们都是awesome@Radanek当前位置我故意不使用yield,因为我不想让您负担过重的新语法和更高级的语法。哦,好吧,赢一些,输一些。