jf93
jf93

Reputation: 31

NameError in Python - not sure if the class or the function is causing the error

I have a text file describing resumes where each line looks like:

name university sex filename

So one line would say something like

John Texas M resume1.doc

The file has standard formatting and does not contain any errors. There are four possible names and four possible universities, randomized to create 64 resumes. I'm trying to write a program that reads through the text file, creates a resume object with attributes for the name, university, sex, and filename, and adds these objects to a list of resume objects. I have a lot of experience in C++, but this is my first Python program and I'm getting thrown off by an error:

File "mycode.py", line 142, in <module>
  resumes()
File "mycode.py", line 65, in resumes
  r = resume(name,uni,sex,filename)
NameError: global name "name" is not defined

My code looks like:

class resume:
    def __init__(self, name, uni, sex, filename)
        self.name = name
        self.uni = uni
        self.sex = sex
        self.filename = filename

mylist[]

def resumes():
    f = open("resumes.txt",'r')
    for line in f:
        for word in line.split():
            if word == ("John" or "Fred" or "Jim" or "Michael"):
                name = word
            elif word == ("Texas" or "Georgia" or "Florida" or "Montana"):
                uni = word
            elif word == "M":
                sex = word
            elif re.match(r'\w\.doc',word):
                filename = word
        r = resume(name,uni,sex,filename)
        mylist.insert(r)

I'm not sure if the error is in the class or the function. My computer isn't showing any syntax errors but I'm new to this so if there are, please feel free to tell me how to fix them.

I've tried defining name, uni, etc. outside the "for word in line.split()" loop but the program still had an issue with the line "r = resume(name,uni,sex,filename)" so I'm not sure what the issue is. I've read through other answers about NameError but I'm new to Python and couldn't figure out the equivalent problem in my code.

Upvotes: 3

Views: 1195

Answers (2)

Daniel
Daniel

Reputation: 2469

Your code is throwing a NameError because at some point in the iteration of your file, some word variable doesn't fulfill any of the conditionals in this line of your function: if word == ("John" or "Fred" or "Jim" or "Michael"):, and name doesn't get defined.

The simplest way to workaround this error is to assign default values to your variables outside the scopes of your class and function (or within the scope of your function):

name = "name"
uni = "uni"
sex = "sex"
filename = "filename"

class resume:
# rest of your code

As an alternative, you could include conditional checks within your function for your variables; if the variable isn't yet defined, assign it a default value:

if "name" not in locals():
    name = "name"
r = resume(name,uni,sex,filename)

Finally, you'll want to append a colon to this line, from this:

def __init__(self, name, uni, sex, filename)

to this:

def __init__(self, name, uni, sex, filename):

change this line where you intialize mylist from this:

mylist[]

to this:

mylist = []

and change:

mylist.insert(r)

to:

mylist.append(r)

Upvotes: 1

jDo
jDo

Reputation: 4010

The NameError is caused by undefined variables in cases where no values are found in the text file. Define them within the function before you try to assign values from the text file to them:

def resumes():
    f = open("resumes.txt",'r')
    for line in f:
        name = ""
        uni = ""
        sex = ""
        filename = ""
        for word in line.split():
            ...

You can also pre-define the variables in your class initialization by using keyword arguments if you like (this isn't the cause of the NameError though):

class resume:
    def __init__(self, name="", uni="", sex="", filename="")
        self.name = name
        self.uni = uni
        self.sex = sex
        self.filename = filename

Defining a list in python is done by typing mylist = [], not mylist[]. Also, at the moment, the list would be defined in the global namespace which is generally discouraged. Instead, you can make resumes return a list and assign this value to mylist:

def resumes():
    resume_list = []
    f = open("resumes.txt",'r')
    for line in f:
        for word in line.split():
            if word == ("John" or "Fred" or "Jim" or "Michael"):
                name = word
            elif word == ("Texas" or "Georgia" or "Florida" or "Montana"):
                uni = word
            elif word == "M":
                sex = word
            elif re.match(r'\w\.doc',word):
                filename = word
        r = resume(name,uni,sex,filename)
        resume_list.insert(r)
    return resume_list

Then you can do the following anywhere in your code:

mylist = resumes()

Remember to close files after opening them; in your case by calling f.close() after processing all the lines. Even better, have python manage it automatically by using the context manager with so you don't have to call f.close():

def resumes():
    with open("resumes.txt",'r') as f:
        for line in f:
            ...

Typically, you'd use append rather than insert when working with lists. insert takes two arguments (position/index, and the element to insert) so mylist.insert(r) should raise a TypeError: insert() takes exactly 2 arguments (1 given). Instead, do mylist.append(r) to insert r after the last element in the list.

As, johnrsharpe pointed out in the comments, your word comparisons probably aren't doing what you expect. See this example:

>>> word = "John"
>>> word == ("John" or "Fred" or "Jim" or "Michael")
True
>>> word = "Fred"
>>> word == ("John" or "Fred" or "Jim" or "Michael")
False
>>> 

Instead, use a tuple or a set and the keyword in to check if word equals any of the four names:

>>> word = "John"
>>> word in {"John", "Fred", "Jim", "Michael"}
True
>>> word = "Fred"
>>> word in {"John", "Fred", "Jim", "Michael"}
True
>>>
>>> type({"John", "Fred", "Jim", "Michael"})
<type 'set'>
>>> 

Finally, as Daniel pointed out, remember the colon, :, after function definitions such as def __init__(...)

Upvotes: 2

Related Questions