0

I have tried writting a function that takes a string of characters and returns the number of words in Enlgish that do not contain any of the characters in the string.

op= open('words.txt')

def avoids(forbidden):
    """counts the number of words in Enlgish which do not contain any
    character found in forbidden str"""
    number=0
    for line in op:
        count=0
        for letter in line.strip():
            if forbidden.count(letter)==0:
                count=count+1
        if count==len(line.strip()):
            number=number+1
    return number

print(avoids('e'))

print(avoids('a'))

When running the program, print(avoids('e')) works fine, printing 37641; however, print(avoids('a')) prints 0. Regardless of the strings I put as arguments in the function calls, the first funtion always returns the correct value, while the second one always returns 0.

I am new to coding so I don't know why this happens and how to solve it. Help please.

AGN Gazer
  • 8,025
  • 2
  • 27
  • 45
  • 2
    Open and close the file *inside* the function. – Silvio Mayolo Jul 19 '18 at 02:10
  • The first dup almost exactly matches your question in a much more obvious way than the others; the second has the best answer. So I just threw in both, plus the others from the list of "canonical" versions of this question. Don't feel like you have to read all the text on all four pages if you figure out how to fix your code and why right away; they're just there in case someone needs them. – abarnert Jul 19 '18 at 03:44

1 Answers1

3

That is because after the loop for line in op: is over, the file was read to the end and there is nothing more to read.

There are several alternatives:

Option 1 (worse): re-open the file:

with open('words.txt') as op:
    print(avoids('e'))

with open('words.txt') as op:
    print(avoids('a'))

Option 2 (better): read all lines and pass them to avoids():

def avoids(forbidden, lines):
    """counts the number of words in Enlgish which do not contain any
    character found in forbidden str"""
    number=0
    for line in lines:
        count=0
        for letter in line.strip():
            if forbidden.count(letter)==0:
                count=count+1
        if count==len(line.strip()):
            number=number+1
    return number

with open('words.txt') as op:
    lines = op.readlines()
    print(avoids('e', lines))
    print(avoids('a', lines))

However, this requires keeping all lines in memory which is OK for smaller files but may be a problem for very large files.

Option 3a (better for very large files):

This is the same as option 1 but has open() placed inside the function.

def avoids(forbidden, filename):
    """counts the number of words in Enlgish which do not contain any
    character found in forbidden str"""
    number=0
    with open(filename) as op:
        for line in op:
            count=0
            for letter in line.strip():
                if forbidden.count(letter)==0:
                    count=count+1
            if count==len(line.strip()):
                number=number+1
    return number

print(avoids('e', 'words.txt'))
print(avoids('a', 'words.txt'))

Option 3b (also good for very large files but I do not like it):

Add op.seek(0) before return number. Alternatively (and likely better), as mentioned by @kindall in the comments, op.seek(0) can be placed at the beginning of the function to make sure we are at the beginning of the file before we start reading lines. This will "rewind" the file to the beginning and allows you to open the file only once outside the function. Essentially, this will make your old function work as expected by you.

AGN Gazer
  • 8,025
  • 2
  • 27
  • 45
  • 1
    Option 3a... put the `seek(0)` at the *beginning* of the function... – kindall Jul 19 '18 at 02:24
  • @juandavidposada Even though my answer fixes the issue in your question, you function does not actually do what you have described you wanted it to do: count the English words not containing any of the characters in `forbidden` string. – AGN Gazer Jul 19 '18 at 02:51
  • @AGNGazer Thanks! As for the function, I have fixed already fixed it. Based on my own trial and error observations, it seems to be doing its job now. – juan david posada Jul 19 '18 at 04:04