AttributeError: 'NoneType' object has no attribute 'lower' python
Question: My abc.txtfile looks like this

    
    
    Mary    Kom     28 F
    Emon    Chatterje  32 M
    Sunil   Singh  35 M
    

Now i am getting the desired result with the following traceback:Please help
me out. I am not getting where am i going wrong

    
    
    Enter for Search Criteria
    1.FirstName  2.LastName  3.Age  4.Gender  5.Exit 1
    Enter FirstName :m
    Mary Kom 28 F
    Emon Chatterje 32 M
    Traceback (most recent call last):
     File "testcode.py", line 50, in <module>
        if (records.searchFName(StringSearch)):
      File "testcode.py", line 12, in searchFName
        return matchString.lower() in self.fname.lower()
     AttributeError: 'NoneType' object has no attribute 'lower'
    

My Code:

    
    
    #!usr/bin/python
    import sys
    
    class Person:
        def __init__(self, firstname=None, lastname=None, age=None, gender=None):
            self.fname = firstname
            self.lname = lastname
            self.age = age
            self.gender = gender
        def searchFName(self, matchString):
    
            return matchString.lower() in self.fname.lower()
    
        def searchLName(self, matchString):
    
            return matchString.lower() in self.lname.lower()
    
        def searchAge(self, matchString):
    
            return str(matchString) in self.age
    
        def searchGender(self, matchString):
    
            return matchString.lower() in self.gender.lower()
    
        def display(self):
    
            print self.fname, self.lname, self.age, self.gender
    
    
    f= open("abc","r")
    list_of_records = [Person(*line.split()) for line in f]
    f.close()
    found = False
    n=0
    
    n1 = raw_input("Enter for Search Criteria\n1.FirstName  2.LastName  3.Age  4.Gender      5.Exit " )
    
    if n1.isdigit():
        n = int(n1)
    else:
        print "Enter Integer from given"
        sys.exit(1)
    if n == 0 or n>5:
        print "Enter valid search "
    if n == 1:
        StringSearch = raw_input("Enter FirstName :")
        for records in list_of_records:
            if (records.searchFName(StringSearch)):
                found = True
                records.display()
    
        if not found:
            print "No matched record"
    
    if n == 2:
        StringSearch = raw_input("Enter LastName :")
        for records in list_of_records:
            if records.searchLName(StringSearch):
                found = True
                records.display()
    
       if not found:
            print "No matched record"
    
    if n == 3:
        StringSearch = raw_input("Enter Age :")
        if (StringSearch.isdigit()):
            StringSearch1 = int(StringSearch)
        else:
            print "Enter Integer"
            sys.exit()
        for records in list_of_records:
            if records.searchAge(StringSearch):
                found = True
            records.display()
    
        if not found:
            print "No matched record"
    
    if n == 4:
        StringSearch = raw_input("Enter Gender(M/F) :")
        for records in list_of_records:
            if records.searchGender(StringSearch):
               found = True
               records.display()
        if not found:
            print "No matched record"
    
    if n == 5:
        sys.exit(1)
    

Please help solve my problrm to where am i going wrong ??


Answer: You have a `Person()` class with no `firstname`. You created it from an empty
line in your file:

    
    
    list_of_records = [Person(*line.split()) for line in f]
    

An empty line results in an empty list:

    
    
    >>> '\n'.split()
    []
    

which leads to `Person(*[])` being called, so a `Person()` instance was
created with no arguments, leaving the default `firstname=None`.

Skip empty lines:

    
    
    list_of_records = [Person(*line.split()) for line in f if line.strip()]
    

You may also want to default to empty strings, or specifically test for `None`
values before treating attributes as strings:

    
    
    def searchFName(self, matchString):
        return bool(self.fname) and matchString.lower() in self.fname.lower()
    

Here `bool(self.fname)` returns `False` for empty or `None` values, giving you
a quick `False` return value when there is no first name to match against:

    
    
    >>> p = Person()
    >>> p.fname is None
    True
    >>> p.searchFName('foo')
    False
    

