Search code examples
pythonlistappendreturn-valuexlrd

return Set of lists from out of function: python


Method collectInfoFromXLS() extracts all the contents which are under quotes ('') from given XLS file, and puts in an List.

class ExtractInfo(object):

    def collectInfoFromXLS():
        workbookPath = config.get('TestCaseFileURL','XLSpath')
        workbook = xlrd.open_workbook(workbookPath)
        SheetPath = config.get('TesCaseSheetName','Sheet1')
        worksheet = workbook.sheet_by_name(SheetPath)
        numOfRows = worksheet.nrows - 1
        curr_row = 0
        row1 = []
        row2 = []
        while curr_row < numOfRows:
           curr_row += 1
           row2 = []
           row = worksheet.row(curr_row)
           for value2 in re.findall(r"'(.*?)'", str(row)):
                row2.append(value2)
           return row2

I get output of this method when I print row2 is like

['', 'MUC-EC-099_SC-Memory-01_TC-1', 'Description1.', '', '', '', '', '', '', '', '', '', '', '', '']
['', 'MUC-EC-099_SC-Memory-01_TC-2', 'Description2', '', '', '', '', '', '', '', '', '', '', '', '']
......

I want to call this method from outside of the class, like

Classobject = ExtractInfo(object)
print Classobject.collectInfoFromXLS()

So that I could get every rows exactly like print inside method, I don't want to append rows2 inside one more list, because it makes problem while retrieving.


Solution

  • Python methods can return only one result at a time.

    That one result can be a list of lists; just return a larger list, and loop over the result:

    result = []
    row2 = []
    while curr_row < numOfRows:
       curr_row += 1
       row2 = []
       row = worksheet.row(curr_row)
       for value2 in re.findall(r"'(.*?)'", str(row)):
            row2.append(value2)
       result.append(row2)
    return result
    

    and:

    for row in Classobject.collectInfoFromXLS():
        print row
    

    A more advanced technique would be to turn your method into a generator function, and yield the rows, one by one. You'd still loop over the method. To make the function a generator, use a yield expression; you can no longer use return with a value once you make it a generator:

    def collectInfoFromXLS():
        workbookPath = config.get('TestCaseFileURL','XLSpath')
        workbook = xlrd.open_workbook(workbookPath)
        SheetPath = config.get('TesCaseSheetName','Sheet1')
        worksheet = workbook.sheet_by_name(SheetPath)
        numOfRows = worksheet.nrows - 1
        curr_row = 0
        row2 = []
        while curr_row < numOfRows:
           curr_row += 1
           row2 = []
           row = worksheet.row(curr_row)
           for value2 in re.findall(r"'(.*?)'", str(row)):
                row2.append(value2)
           yield row2
    

    You still have to loop over the output:

    for row in Classobject.collectInfoFromXLS():
        print row
    

    only now Classobject.collectInfoFromXLS() returns a generator object instead of a list, and you can loop over that object only once.