Python:帮助,函数不能产生我想要的
我试着做一个collatz序列,当我输入初始整数时,它会连续打印出数字,直到它达到1,但是它工作得不太好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 //
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,因为我不想让您负担过重的新语法和更高级的语法。哦,好吧,赢一些,输一些。