-1

I know you can populate lists using a one line "x for x in y" style loop, is it possible to do it using with?

I tried pulling all lines from a text file into a list and it didn't seem to work, at least not the way I tried it.

I tried:

lines = [ x with open("text.txt").readlines() as x]

and

lines = [ x.readlines() with open("text.txt") as x]

which would seem to use the same format but gives me an invalid syntax error. I appreciate I could do it with a for but I'd like to save myself the job of using a close()

Is this possible or am I grasping at straws? This is Python 2 by the way.

timgeb
  • 76,762
  • 20
  • 123
  • 145
Keef Baker
  • 641
  • 4
  • 22
  • Not seeing how, that's an explanation of how with works rather than whether you can manipulate the shape of a with statement, you can manipulate the shape of fors and ifs. I appreciate with is a statement rather than a loop but it can act as one which is why I was wondering about the potential shape change. – Keef Baker Dec 18 '15 at 11:59
  • Although I do now understand that it is a statement rather than a loop. – Keef Baker Dec 18 '15 at 12:01
  • 1
    Well, the *second question* in that question was asking for *What do you use it for?* – Remi Guan Dec 18 '15 at 12:07
  • I think you misread, sorry. This was entirely about whether you can reshape the with statement. I've used with comfortably before and after re-examining it with the replies, I can see that while I was using it right prior to my attempt at a one-line reformat I didn't fully understand it, so that would have answered the IMPLIED question but still wouldn't have answered the PRIMARY question which was can you reformat with statements into one liners in a similar way to for loops. – Keef Baker Dec 18 '15 at 12:47

4 Answers4

4

While this one-liner works:

with open('file.txt') as fobj: lines = list(fobj)

using with with pythonic syntax, you need two lines:

with open('file.txt') as fobj:
    lines = list(fobj)

Here fobj is an iterator that allows efficient line-by-line iteration. Converting it into a list with list(fob has the same effect as fobj.readlines().

Mike Müller
  • 82,630
  • 20
  • 166
  • 161
1

Comprehensions can only use the for statement, not the with statement. You can only do (and there's no reason why you shouldn't)

with open("text.txt") as x:
    lines = x.readlines()
Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
1

with is a context manager and can't be put in one line. And as BDFL once said, "Why do we need to save lines? We are not Perl." (as in, no we don't need to save lines.)

You could just do it in two:

with open("text.txt", "r") as x:
    lines = x.readlines()
aneroid
  • 12,983
  • 3
  • 36
  • 66
-4
lines = open("test.txt").readlines()

There's no need to use a list comprehension here, and the file isn't kept open when you're done anyway.

Btw, it can be combined with a list comprehension if you need it, something like:

lines = [l.strip() for l in open("test.txt").readlines()]
mephisto
  • 661
  • 1
  • 6
  • 14
  • You still need to close the file afterwards though. – SiHa Dec 18 '15 at 10:59
  • Actually, no. Since no reference to the file object is kept, it will automatically be cleaned up. In the case of file objects, this also means the file handle will be closed – mephisto Dec 18 '15 at 11:02
  • That the file is closed after the file object goes out of scope is an implementation detail of cPython's use of reference counting, and you shouldn't rely on that behaviour. It's definitely not true for other python implementations like pypy or jython. – mata Dec 18 '15 at 11:05
  • 1
    Then why have the `with open(file) as fileobject` construct at all? Relying on the garbage collector to close your file handles is bad practise. – SiHa Dec 18 '15 at 11:05
  • I'll admit i have no experience with pypy or jython, but frankly I don't see why it would be strange to at least expect this to work. I'm not keeping a reference to an object, so I'm done using it. Ergo, no need to keep a file handle open. Call me lazy, but I'm used to things making that much sense in python. I guess there's no point in complaining if my own ignorance was the problem, but I'm surprised that it's not this intuitive across all implementations. Anyway, I appreciate the feedback. – mephisto Dec 18 '15 at 11:15
  • From [The Zen of Python](https://www.python.org/dev/peps/pep-0020/): "Explicit is better than implicit." - It is better to explicitly close the handle that rely on some background process do (maybe) do it for you. `with` does this. – SiHa Dec 18 '15 at 11:18
  • That's a good point :) – mephisto Dec 18 '15 at 11:22