3
votes

Automatisez le projet Boring Stuff Collatz

Je travaille actuellement sur le projet collatz dans le chapitre 3 d'Automate the Boring Stuff. J'ai une fonction collatz entièrement fonctionnelle pour les entrées entières, mais je suis bloqué en essayant de faire exécuter le programme lorsque j'ajoute try, sauf les instructions pour les valeurs non entières.

Voici mon code qui ne fonctionne que pour les entrées entières:

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

Maintenant, voici mon code lorsque j'ajoute une instruction 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)

et voici le code d'erreur Je reçois:

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)

Pour être clair, ce programme fonctionne lorsque je lance un entier immédiatement, mais il ne fonctionne pas lorsque je lance un entier après avoir tapé un string. Si quelqu'un pouvait aider, je l'apprécierais. Merci!


1 commentaires

Dans le cas récursif, vous renvoyez implicitement None. Lorsque vous abandonnez une fonction Python via un chemin de code sans instruction de retour, c'est un retour implicite Aucun


3 Réponses :


3
votes

Le cas récursif ne renvoie rien, donc le contrôle atteint la fin de la fonction lorsque la pile d'appels se résout (les fonctions Python renvoient implicitement None , d'où votre erreur). Changez la ligne:

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)

en

return integercheck(input())

ou évitez complètement la récursivité. Quelques remarques supplémentaires:

  • Évitez d ' imprimer dans votre fonction. Cet effet secondaire le rend moins réutilisable.
  • input ("") prend une chaîne d'invite dont il vaut la peine de profiter.
  • Utilisez snake_case en Python par PEP8 a >
  • collatz ne fait qu'une étape de la séquence, donc le nom est un peu trompeur. Le fardeau de définir la prochaine itération incombe à l'appelant, mais cela lui donne une certaine flexibilité pour déterminer quoi faire avec les valeurs intermédiaires. Dans cet esprit, cette fonction semble être la solution idéale pour la refactorisation vers un générateur , donnant la possibilité de prendre des éléments un à la fois ou d'exécuter la séquence entière comme le code appelant le souhaite.

Une réécriture possible:

integercheck(input())


1 commentaires

Je vous remercie! Donc, l'ajout de return donne à la fonction une valeur de retour au lieu d'être nulle .. semble si simple mais je ne le savais pas. Aussi, un code vraiment intéressant que je n'ai jamais vu auparavant, je vais l'ajouter à mon arsenal. Merci!



0
votes

Étant donné que ce livre est un guide pour débutants sur Python, et je suis n00basF, le code que j'ai écrit pour que cela fonctionne est le suivant:

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)


2 commentaires

Bienvenue à SO! Je n'ai pas essayé votre réponse mais vérifiez la réponse @ggorlen. Il y a des «erreurs» courantes dans la vôtre.


Merci @David Garcia Bodeg. Comme je l'ai dit, je suis nouveau dans ce domaine. Je voulais publier mon code tel qu'il était car j'ai tendance à trouver beaucoup de réponses que les nouvelles personnes demandent impliquent des sujets avancés ou des explications / des sujets que je n'ai pas encore appris, donc je voulais publier un code extrêmement basique. Merci pour la critique constructive. Je suis retourné lire la réponse de ggorlen. Ses conseils ont beaucoup de sens. Je vais certainement travailler sur la refactorisation de mon code et mettre en œuvre ses conseils au fur et à mesure que j'apprendrai plus et que j'acquerrai plus de connaissances et de compréhension.



0
votes

Mon code est ci-dessous. Pour faire la gestion des exceptions, je le mets dans une boucle while qui se rompt pour appeler la fonction collatz.

Dans ma fonction collatz, il teste pour voir si le nombre est 1 en premier, puis vérifie si le nombre est pair ou impair, et poursuit l'opération pour créer le nouveau numéro et l'imprime. J'appelle la fonction collatz de manière récursive dans mes blocs pairs / impairs en utilisant mon nouveau numéro.

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)


1 commentaires

Conseil de pro: vous pouvez utiliser le numéro // 2 pour plancher automatiquement le résultat afin de ne pas avoir à appeler int () encore et encore