B. Chiu
B. Chiu

Reputation: 11

Python: NameError: name "string" is not defined, not via input()

The function below checks to see if the first 9 digits of string (n) equate to the 10th character (an integer from 1-9 or X for 10).

def isISBN(n):
    checkSum = 0
    for i in range(9):
         checkSum = checkSum + (eval(n[i])*(i+1))

    if checkSum%11 == eval(n[9]) or (checkSum%11 == 10 and n[9] == 'X'): return True
    else: return False

When I run the function for n='020103803X' I get an error:

NameError: name 'X' is not defined

I've searched for this problem and found that most people's issues were with input() or raw_input(), but as I am not using input(), I'm confused as to why I can't test if a character is a specific string. This is my first post as Python beginner, please tell if I'm breaking rules or what extra info I should include.

Upvotes: 1

Views: 9520

Answers (4)

Bryan Oakley
Bryan Oakley

Reputation: 385970

The problem is with your use of eval: eval('X') is the same as doing X (without the quotes). python sees that as a variable reference, and you have no variable named X.

There is no reason to use eval here. What are you hoping to accomplish? Perhaps you should be checking to see if the character is a digit?

if checkSum%11 == n[9].isdigit() or (checkSum%11 == 10 and n[9] == 'X'): return True

Upvotes: 2

B. Chiu
B. Chiu

Reputation: 11

Thanks everyone. I don't know how I didn't think of using int(). The reason I used eval() was because the past few programs I wrote required something like

x = eval(input("Input your equation: "))

Anyways the function works now.

def isISBN(n):
    checkSum = 0
    for i in range(9):
        checkSum = checkSum + (int(n[i])*(i+1))

    if n[9] == 'X':
        if checkSum%11 == 10: return True
        else: return False
    elif checkSum%11 == int(n[9]): return True
    else: return False

Upvotes: 0

sabbahillel
sabbahillel

Reputation: 4425

Eval is not the proper usage, nor is the way you use it correct. For example, see Wikipedia which shows the use. You probably want to use a try: except: pair.

try:
     int(n[i]
except:
     print "this character is not a digit"

A call to eval is sometimes used by inexperienced programmers for all sorts of things. In most cases, there are alternatives which are more flexible and do not require the speed penalty of parsing code.

For instance, eval is sometimes used for a simple mail merge facility, as in this PHP example:

$name = 'John Doe';
$greeting = 'Hello';
$template = '"$greeting,
$name! How can I help you today?"';
print eval("return $template;");

Although this works, it can cause some security problems (see § Security risks), and will be much slower than other possible solutions. A faster and more secure solution would be changing the last line to echo $template; and removing the single quotes from the previous line, or using printf.

eval is also sometimes used in applications needing to evaluate math expressions, such as spreadsheets. This is much easier than writing an expression parser, but finding or writing one would often be a wiser choice. Besides the fixable security risks, using the language's evaluation features would most likely be slower, and wouldn't be as customizable.

Perhaps the best use of eval is in bootstrapping a new language (as with Lisp), and in tutoring programs for languages[clarification needed] which allow users to run their own programs in a controlled environment.

For the purpose of expression evaluation, the major advantage of eval over expression parsers is that, in most programming environments where eval is supported, the expression may be arbitrarily complex, and may include calls to functions written by the user that could not have possibly been known in advance by the parser's creator. This capability allows you to effectively augment the eval() engine with a library of functions that you can enhance as needed, without having to continually maintain an expression parser. If, however, you do not need this ultimate level of flexibility, expression parsers are far more efficient and lightweight.

Upvotes: 0

Prune
Prune

Reputation: 77837

You're trying to get a response from

eval('X')

This is illegal, as you have no symbol 'X' defined.

If you switch the order of your if check, you can pass legal ISBNs. However, it still fails on invalid codes with an X at the end.

def isISBN(n):
    checkSum = 0
    for i in range(9):
        checkSum = checkSum + (eval(n[i])*(i+1))

    if (checkSum%11 == 10 and n[9] == 'X') or \
            checkSum%11 == eval(n[9]):
        return True
    else:
        return False

Note also that you can short-cut that return logic by simply returning the expression value:

return (checkSum%11 == 10 and n[9] == 'X') or \
        checkSum%11 == eval(n[9])

Upvotes: 0

Related Questions