我可以查看一下第三章的Collatz序列用Python自动完成无聊的工作的代码吗?
Collatz序列编写一个名为collatz()的函数,该函数有一个名为number的参数。如果数字是偶数,那么collatz()应该打印number // 2并返回这个值。如果数字是奇数,那么collatz()应该打印并返回3* number + 1。然后编写一个程序,让用户输入一个整数,并一直对该数字调用collatz(),直到函数返回值1。(令人惊讶的是,这个序列实际上适用于任何整数-使用这个序列,迟早会达到1!)就连数学家也不知道为什么。您的程序正在探索所谓的Collatz序列,有时被称为“最简单的不可能的数学问题”)。记住用int()函数将输入()的返回值转换为整数;否则,它将是一个字符串值。提示:整数是偶数%2 == 0,如果数字为%2 == 1,则为奇数。该程序的输出可能如下所示:输入编号:3 10 5 16 8 4 2 1输入验证向上一个项目添加try和The语句,以检测用户是否键入非整数字符串。通常,int()函数如果传递一个非整数字符串,就会引发ValueError错误,如int(‘幼犬’)中所示。在enter子句中,打印一条消息给用户,说明他们必须输入一个整数。
我主要想知道是否有一个更干净的方法来写我的解决方案。
def collatz(num):
while num > 1:
if num % 2 == 0:
print(num//2)
num = num //2
elif num % 2 ==1:
print(3*num+1)
num = 3*num+1
else:
print(num)
def getNum():
global num
num = (input("> "))
try:
num = int(num)
except ValueError:
print('plese enter a number')
getNum()
getNum()
collatz(num)发布于 2019-09-18 21:29:59
首先,注意重复计算的方式:
print(num//2)
num = num //2这可能不会引起这个特定代码的问题,但这不是一个好的实践。您所做的工作是所需的两倍,一旦开始编写更复杂的代码,就会导致性能问题。进行一次计算,并保存结果。不过,在这种情况下,您所需要做的就是反转这些行并使用num:
num = num // 2
print(num)此外,确保您有适当的间隔围绕运算符,并保持一致。
您的if和elif案例是相互排斥的,您的else不应该发生。如果第一个条件为真,则其他条件必须是假的,反之亦然。没有必要再做第二次检查。一旦重写,您将看到打印在每一种情况下是不必要的。你只需在以下几个地方打印:
while num > 1:
if num % 2 == 0:
num = num // 2
else:
num = 3 * num + 1
print(num)由于您只是根据条件重新组合num的两个选项之一,这里还可以清晰地使用条件表达式:
while num > 1:
num = (num // 2) if num % 2 == 0 else (3 * num + 1)
print(num)大括号是不必要的,但我认为它们在这里是有用的,因为涉及的操作符很多。
在这里打印数字并不理想。在大多数代码中,您需要能够使用您生成的数据。如果您想分析产生的序列,您将不得不做一些拦截标准输出,这是昂贵和过于复杂的。使其成为累加并返回列表的函数。在下面的示例中,我还添加了一些类型提示,以使数据的类型更加清晰:
from typing import List
def collatz(starting_num: int) -> List[int]:
nums = [starting_num]
num = starting_num
while num > 1:
num = (num // 2) if num % 2 == 0 else (3 * num + 1)
nums.append(num)
return nums或者,一种更简洁的方法是使其成为一个产生数字的生成器:
# Calling this function returns a generator that produces ints
# Ignore the two Nones, as they aren't needed for this kind of generator
def collatz_gen(starting_num: int) -> Generator[int, None, None]:
yield starting_num
num = starting_num
while num > 1:
num = (num // 2) if num % 2 == 0 else (3 * num + 1)
yield num
>>> list(collatz_gen(5))
[5, 16, 8, 4, 2, 1]关于getNum,有几个值得注意的地方:
Python使用“蛇”使用“蛇”,不是"camelCase“
您在这里使用global num是不必要的,也是令人困惑的。和以前一样,显式地return函数生成的任何数据:
def get_num() -> int:
raw_num = input("> ")
try:
return int(raw_num)
except ValueError:
print('Please enter a number')
return get_num()注意,我们不是重新分配全局num,而是返回数字。我还用了一些比较合适的名字,把东西分开了一些。从概念上讲,我认为num = input("> ")是错误的。在运行时,num不包含数字(它包含一个字符串)。
这不是递归的好使用。这很可能不会给你带来任何问题,但是如果你的用户真的很笨,输入错误的数据1000次,你的程序就会崩溃。只需使用循环:
def get_num() -> int:
while True:
raw_num = input("> ")
try:
return int(raw_num)
except ValueError:
print('Please enter a number')在Python等语言中,在无法保证函数递归次数的情况下,请小心使用递归。
我也可能会把它命名为更接近ask_for_num的东西。"get“并不能清楚地说明数据来自何处。
总之,你最终会得到:
from typing import Generator
def collatz_gen(starting_num: int) -> Generator[int, None, None]:
yield starting_num
num = starting_num
while num > 1:
num = (num // 2) if num % 2 == 0 else (3 * num + 1)
yield num
def ask_for_num() -> int:
while True:
raw_num = input("> ")
try:
return int(raw_num)
except ValueError:
print('Please enter a number')可用于:
num = ask_for_num()
for n in collatz_gen(num):
print(n)发布于 2019-09-18 22:14:57
这里最明显的错误做法是使用全局变量。您的函数不应将num设置为副作用,而是应该对结果进行return。
getNum()不是这个函数的好名称。PEP 8是Python的官方风格指南,它说函数名应该是lower_case_with_underscores。此外,"get“意味着函数正在检索已经存储在某个地方的数据,这里的情况并非如此。最后,"Num“应该更具体。
使用递归是不合适的。如果你想要一个循环,就写一个循环。
def ask_integer():
"""
Return an integer entered by the user (repeatedly prompting if
the input is not a valid integer).
"""
while True:
try:
return int(input("> "))
except ValueError:
print("Please enter an integer")
num = ask_integer()collatz函数严格地说,你没有遵守指示。您的解决方案没有错或坏--您只是没有按照给定的规范实现collatz函数,该规范规定您应该打印并返回一个数字。
def collatz(num):
"""
Given a number, print and return its successor in the Collatz sequence.
"""
next = num // 2 if num % 2 == 0 else 3 * num + 1
print(next)
return next
num = ask_integer()
while num > 1:
num = collatz(num)发布于 2019-09-19 08:22:01
为了完整起见,collatz的递归实现(您已经获得了足够多的输入num的好建议):
def collatz(num):
print(num)
if num == 1:
return num
if num % 2 == 0:
return collatz(num // 2)
return collatz(3 * num + 1)
collatz(3)输出
3
10
5
16
8
4
2
1https://codereview.stackexchange.com/questions/229270
复制相似问题