【问题标题】:Automate the Boring Stuff Collatz Project自动化无聊的东西 Collat​​z 项目
【发布时间】:2020-09-15 15:16:55
【问题描述】:

我目前正在处理 Automate the Boring Stuff 第 3 章中的 collat​​z 项目。我有一个完整的整数输入 collat​​z 函数,但是当我添加 try 时,我一直试图让程序运行,但非整数值的语句除外。

这是我的代码,仅适用于整数输入:

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

print('Type in a number: ')
colNum = int(input())

while colNum != 1:
        colNum = collatz(colNum)

现在,这是我添加 try/except 语句时的代码:

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

def integercheck(inputVal):
    try:
        return int(inputVal)
    except ValueError:
        print('Error: Input needs to be a number.')
        print('Type in a number: ')
        integercheck(input())

print('Type in a number: ')
colNum = integercheck(input())

while colNum != 1:
        colNum = collatz(colNum)

这是我收到的错误代码:

Type in a number: 
string
Error: Input needs to be a number.
Type in a number: 
string
Error: Input needs to be a number.
Type in a number: 
5
Traceback (most recent call last):
  File "/Users/Library/Preferences/PyCharmCE2018.2/scratches/scratch_1.py", line 22, in <module>
    colNum = collatz(colNum)
  File "/Users/Library/Preferences/PyCharmCE2018.2/scratches/scratch_1.py", line 3, in collatz
    if number % 2 == 0:
TypeError: unsupported operand type(s) for %: 'NoneType' and 'int'

Process finished with exit code 1

需要明确的是,当我立即输入一个整数时,这个程序可以工作,但是当我在输入一个字符串后输入一个整数时,它就无法工作。如果有人可以提供帮助,我将不胜感激。谢谢!

【问题讨论】:

  • 在递归情况下,您隐式返回 None。当您通过任何没有返回语句的代码路径退出 Python 函数时,这就是隐式 return None

标签: python python-3.x


【解决方案1】:

递归情况不返回任何内容,因此当调用堆栈解析时,控制到达函数的末尾(Python 函数隐式返回 None,因此您的错误)。换行:

integercheck(input())

return integercheck(input())

或完全避免递归。补充几点:

  • 避免在函数中使用printing。这个side effect 使它的可重用性降低。
  • input("") 采用值得利用的提示字符串。
  • 根据PEP8 在 Python 中使用 snake_case
  • collatz 只做序列的一步,所以名字有点误导。设置下一次迭代的负担落在调用者身上,但这确实给调用者一些灵活性来决定如何处理中间值。考虑到这一点,这个函数似乎非常适合重构为 generator,从而能够一次获取一个元素或在调用代码认为合适的情况下运行整个序列。

可能的重写:

def collatz(n):
    while n > 1:
        if n % 2 == 0:
            n //= 2
        else:
            n = 3 * n + 1

        yield n

def get_int(prompt="Enter a number: ", 
            err="Error: Input needs to be a number."):
    while True:
        try:
            return int(input(prompt))
        except ValueError:
            print(err)

if __name__ == "__main__":
    for step in collatz(get_int()):
        print(step)

【讨论】:

  • 谢谢!所以添加 return 会给函数一个返回值而不是 null .. 看起来很简单,但我不知道。另外,我以前从未见过的非常有趣的代码,我会把它添加到我的库中。谢谢!
【解决方案2】:

鉴于这本书是 Python 的初学者指南,而我是 n00basF,我编写的代码如下:

def collatz(number):
   try:
      number = int(number)
      while (number) != 1:
        if number % 2 == 0:
            number = number // 2
            print(number)

        elif number % 2 == 1:
            number = 3 * number + 1
            print(number)   
        else:
            break
    except ValueError:
        print('ERROR!!! You need to enter an integer.')

print('Enter a number: ')
userNumber = input('>> ')

collatz(userNumber)

【讨论】:

  • 欢迎来到 SO!我没有尝试您的答案,但请查看@ggorlen 回复。你有一些常见的“错误”。
  • 感谢@David Garcia Bodeg。就像我说的那样,我对此很陌生。我想发布我的代码,因为我倾向于找到很多新人提出的答案,涉及我尚未学习的高级主题或解释/主题,所以我想发布非常基本的代码。感谢您的建设性批评。我回去看了ggorlen的回答。他的建议很有道理。随着我了解更多并获得更多知识和理解,我一定会重构我的代码并实施他的建议。
【解决方案3】:

我的代码如下。为了进行异常处理,我将它放在一个 while 循环中,该循环会中断以调用 collat​​z 函数。

在我的 collat​​z 函数中,它首先测试数字是否为 1,然后继续检查数字是偶数还是奇数,然后继续操作以创建新数字并打印它。我使用我的新号码在奇数/偶数块内递归调用 collat​​z 函数。

def collatz(number):

    if int(number) == 1:
        print('')
             
    elif int(number) % 2 == 0:
        newNumber = int(number / 2)
        print(newNumber)
        collatz(newNumber)

    elif int(number) % 2 == 1:
        newNumber = int(3 * number + 1)
        print(newNumber)
        collatz(newNumber)
    
print('Enter a number:')    
while True:         
    try:
        number = int(input())
        break
    except ValueError:
        print('Please enter a NUMBER:')

collatz(number)

【讨论】:

  • 专业提示:您可以使用number//2 自动调整结果,这样您就不必一遍又一遍地调用int()
猜你喜欢
  • 2020-05-14
  • 1970-01-01
  • 2020-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-22
  • 2017-09-13
相关资源
最近更新 更多