WildCat
WildCat

Reputation: 19

Loop within a loop not re-looping with reading a file Python3

Trying to write a code that will find all of a certain type of character in a text file For vowels it'll find all of the number of a's but won't reloop through text to read e's. help?

def finder_character(file_name,character):

    in_file = open(file_name, "r")

    if character=='vowel':
        brain_rat='aeiou'
    elif character=='consonant':
        brain_rat='bcdfghjklmnpqrstvwxyz'
    elif character=='space':
        brain_rat=''
    else:
        brain_rat='!@#$%^&*()_+=-123456789{}|":?><,./;[]\''       

    found=0 
    for line in in_file:
        for i in range (len(brain_rat)):
            found += finder(file_name,brain_rat[i+1,i+2])


    in_file.close()
    return found

def finder(file_name,character):
    in_file = open(file_name, "r")
    line_number = 1
    found=0
    for line in in_file:
        line=line.lower()
        found +=line.count(character)
    return found

Upvotes: 1

Views: 105

Answers (2)

Steinar Lima
Steinar Lima

Reputation: 7821

If you want to use your original code, you have to pass the filename to the finder() function, and open the file there, for each char you are testing for.

The reason for this is that the file object (in_file) is a generator, not a list. The way a generator works, is that it returns the next item each time you call their next() method. When you say

for line in in_file:

The for ... in statement calls in_file.next() as long as the next() method "returns" (it actually use the keyword yield, but don't think about that for now) a value. When the generator doesn't return any values any longer, we say that the generator is exhausted. You can't re-use an exhausted generator. If you want to start over again, you have to make a new generator.

I allowed myself to rewrite your code. This should give you the desired result. If anything is unclear, please ask!

def finder_character(file_name,character):

    with open(file_name, "r") as ifile:
        if character=='vowel':
            brain_rat='aeiou'
        elif character=='consonant':
            brain_rat='bcdfghjklmnpqrstvwxyz'
        elif character=='space':
            brain_rat=' '
        else:
            brain_rat='!@#$%^&*()_+=-123456789{}|":?><,./;[]\'' 

    return sum(1 if c.lower() in brain_rat else 0 for c in ifile.read())

test.txt:

eeehhh
iii!#
kk ="k
oo o

Output:

>>>print(finder_character('test.txt', 'vowel'))
9
>>>print(finder_character('test.txt', 'consonant'))
6
>>>print(finder_character('test.txt', 'space'))
2
>>>print(finder_character('test.txt', ''))
4

If you are having problems understanding the return line, it should be read backwards, like this:

Sum this generator:
    Make a generator with values as v in:
        for row in ifile.read():
            if c.lower() in brain_rat:
                v = 1
            else:
                v = 0

If you want to know more about generators, I recommend the Python Wiki page concerning it.

Upvotes: 2

user764357
user764357

Reputation:

This seems to be what you are trying to do in finder_character. I'm not sure why you need finder at all.

In python you can loop over iterables (like strings), so you don't need to do range(len(string)).

for line in in_file:
    for i in brain_rat:
        if i in line: found += 1

There appear to be a few other oddities in your code too:

  • You open (and iterate through) the file twice, but only closed once.
  • line_number is never used
  • You get the total of a character in a file for each line in the file, so the total will be vastly inflated.

This is probably a much safer version, with open... is generally better than open()... file.close() as you don't need to worry as much about error handling and closing. I've added some comments to help explain what you are trying to do.

def finder_character(file_name,character):
    found=0    # Initialise the counter
    with open(file_name, "r") as in_file:
        # Open the file
        in_file = file_name.split('\n')

        opts = { 'vowel':'aeiou',
                 'consonant':'bcdfghjklmnpqrstvwxyz',
                 'space':'' }
        default= '!@#$%^&*()_+=-123456789{}|":?><,./;[]\''

        for line in in_file:
            # Iterate through each line in the file
            for c in opts.get(character,default):
                With each line, also iterate through the set of chars to check.
                if c in line.lower():
                    # If the current character is in the line
                    found += 1  # iterate the counter.
    return found    # return the counter

Upvotes: 2

Related Questions