1

Here is my code:

def retest2():
    print "Type in another chapter title! Or type \"Next\" to move on."
    primenumbers2()
def primenumbers1():
    print "--------------------------------------------------\nChapters in books are usually given the cardinal numbers 1, 2, 3, 4, 5, 6 and so on.\nBut I have decided to give my chapters prime numbers 2, 3, 5, 7, 11, 13 and so on because I like prime numbers.\n\nType in the chapter title of my book (a prime number) and I will tell you what cardinal number the chapter is."
def primenumbers2():
    prime = (str(input("\n")))
    chapter = (2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233)

    if "Next" in prime or "next" in prime:
        print "--------------------------------------------------\nOnto the next thing."
    elif int(prime) in chapter:
        print "Chapter ",chapter.index(int(prime)) + 1
        retest2()
    elif prime.isalpha:
        print "That is not one of my chapter numbers because {0} is not a prime number. Try again.".format(prime)
        primenumbers2()

primenumbers1()
primenumbers2()

So what I'm trying to do is having the user input a prime number and the output is the cardinal number correlating to that prime number. However, I want the user to have the option of going onto the next function by typing in "Next" or "next". Therefore, my variable input prime needs to accomodate for both string and integer input. So I set it as (str(input("\n"))) and then I converted it to int(prime) when I needed to.

Everything works well except when the string input is anything but "Next" or "next". For example, if I input "okay", I get the error message:

File "prime.py", line x, in primenumbers2
    prime = (str(input("\n")))
  File "<string>", line 1, in <module>
NameError: name 'okay' is not defined

But if I input "4", which is NOT a prime number, the program works and I get:

That is not one of my chapter numbers because 4 is not a prime number. Try again.

And the program loops back to primenumbers2() to restart that function.

Please help me make this work!

theo1010
  • 127
  • 10

3 Answers3

2

You need to use raw_input for python2, input in python2 is basically eval(raw_input()) and as you have no variable okay defined you get the error.

In [10]: prime = (str(input("\n")))

foo
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-10-15ff4b8b32ce> in <module>()
----> 1 prime = (str(input("\n")))

<string> in <module>()

NameError: name 'foo' is not defined    
In [11]: foo = 1 
In [12]: prime = (str(input("\n")))
foo
In [13]: prime = (raw_input("\n"))
next
In [14]: print prime
next

You should rarely if ever use input.

You should also use a while loop, something like the following:

 def primenumbers2():
    chapter = (
        2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107,
        109,
        113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233)
    while True:
        prime = input("Type in another chapter title! Or type \"Next\" to move on.")
        if "next"  == prime.lower():
            print("--------------------------------------------------\nOnto the next thing.")
            break
        try:
            p = int(prime)
            if p in chapter:
                print("Chapter {}".format(chapter.index(p) + 1))
            else:
                 print("That is not one of my chapter numbers because {0}"
                  " is not a prime number. Try again.".format(prime))
        except ValueError:
            print("Invalid input")

Not totally sure what you want to do but using a while, checking if the user input is equal to next and if not trying to cast to int using a try/except is a better idea.

Making chapters a dict would also be a better idea, accessing the chapter number by key:

def primenumbers2():
    chaps = (
        2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107,
        109,
        113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233)

    chapter = dict(zip(chaps, range(1, len(chaps) + 1)))
    while True:
        prime = input("Type in another chapter title! Or type \"Next\" to move on.")
        if "next" == prime.lower():
            print("--------------------------------------------------\nOnto the next thing.")
            break
        try:
            p = int(prime)
            if p in chapter:
                print("Chapter {}".format(chapter[p]))
            else:
                print("That is not one of my chapter numbers because {}"
                      " is not a prime number. Try again.".format(prime))
        except ValueError:
            print("Invalid input")

range(1, len(chaps) + 1)) will mean each p in chapter will have a value corresponding to its index in the tuple.

Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
  • Thank you, I used a variation of this and it works. Instead of putting `else` outside of the `try` block, I put `elif p not in chapter` within the `try` block. – theo1010 May 16 '15 at 21:38
  • @theo1010, no prob, I pasted the wrong code, you need to break the while when the user enters next or call some other function if that is what you had planned. I was not totally sure what your full idea was. – Padraic Cunningham May 16 '15 at 21:46
1

What you're trying to do is converting a value entered by the user to a string or an int. If you use input, which as Padraic says is equals to eval(raw_input()), you will eval the input as it was a python command: this will throw an error if you write any non existing name. To resolve this, use the raw_input function. It will return a str object, the input text.

Then, you want to find if this text is a number, or a string. One solution is using exceptions :

try:
    prime = int(prime)

    # Here the code assuming prime is a number, an `int`
except ValueError:
    # here the code assuming prime is a string, `str`, for example
    # 'Next', 'next' or 'okay'
Spirine
  • 1,837
  • 1
  • 16
  • 28
  • If I type in a number that is not prime, I get an error message: `AttributeError: 'int' object has no attribute 'isalpha'` – theo1010 May 16 '15 at 17:54
  • @theo1010 Sorry, I paste your code without checking... If prime is a number, then the execution of the code will continue after `prime = int(prime)`, and prime will be an `int`. So, you must do the code assuming prime is an `int`. – Spirine May 16 '15 at 18:01
0

Try using isdigit to avoid the exception:

def primenumbers2():
prime = (str(input("\n")))
chapter = (2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233)

if "Next" in prime or "next" in prime:
    print "--------------------------------------------------\nOnto the next thing."
elif prime.isdigit() and int(prime) in chapter:
    print "Chapter ",chapter.index(int(prime)) + 1
    retest2()
else:
    print "That is not one of my chapter numbers because {0} is not a prime number. Try again.".format(prime)
    primenumbers2()
Owbea
  • 1
  • 2