Opening a file

I am reading [Python Crash Course] and learning how to open a file. I came across this code and wondering of what type “filename” is. The code below suggests it is a list of lines because for loop iterates through it. But when I use ‘type(f)’, some strange output is produced.
<_io.TextIOWrapper name=‘learning_python.txt’ mode=‘r’ encoding=‘cp949’>

I don’t know what that is, and how a for loop could iterate through it even when it is not a list.

filename = 'pi_digits.txt'

with open(filename) as f:
    for line in f:
        print(line)

You must select a tag to post in this category. Please find the tag relating to the section of the course you are on E.g. loops, learn-compatibility

When you ask a question, don’t forget to include a link to the exercise or project you’re dealing with!

If you want to have the best chances of getting a useful answer quickly, make sure you follow our guidelines about how to ask a good question. That way you’ll be helping everyone – helping people to answer your question and helping others who are stuck to find the question and answer! :slight_smile:

Hi there.

If you really want to know what’s going on “under the hood”, so to speak, when you open a file with Python then the documentation is the best place to go.

The short answer is that f is a file object. As you’re opening a text file, f is an instance of the io.TextIOWrapper class.

That “strange output” is Python showing you a representation of the object, which would make sense when written to the terminal. You can see that it is an instance of io.TextIOWrapper, that the file you opened was learning_python.txt, that you have opened it in r read mode and that the file encoding is cp949.

You’re right that it’s not a list, but yet the file object is iterable.

This is because the io.TextIOWrapper class inherits from another class, called io.TextIOBase. That, in turn, inherits from io.IOBase. As a diagram, it looks like this:

io.IOBase   --->   io.TextIOBase   --->   io.TextIOWrapper
(base)             (sub-class)            (2nd sub-class)

(Don’t worry if you don’t fully understand classes and inheritance just yet.)

The base class, io.IOBase, supports the iterator protocol and - thanks to inheritance - so do its subclasses.

Since IOBase understands iteration - the process of saying “for every item in this sequence”, as we’re doing with for line in file: - this is how we can iterate with the for loop on io.TextIOWrapper, as it is a subclass derived from io.IOBase.

Hopefully that makes sense… but let us know if anything is still unclear.

2 Likes