Reputation: 529
Please explain:
>>> [line.rstrip() for line in open('foo')]
[',' 'hello text file6', '', '', '', 'goodby text file7', '', 'bye', '']
>>> with open('foo') as f: [line.rstrip() for line in f if line.rstrip()[-1:].isdigit()]
...
['hello text file6', 'goodby text file7']
[-1:] ignores empty strings while list comprehension above has them.So far I'm accustomed that slices work only within one single string. [-1:] slice seems crossed the boundaries of many strings.
Upvotes: 0
Views: 71
Reputation: 82058
Breaking things down:
Slices ([::]
syntax) will address all possible values in the range. That means all of these are true.
['cat'][0:1] == ['cat']
['cat'][1:2] == []
['cat'][-1:2] == ['cat']
['cat'][-10000:] == ['cat']
Accessing something by index on the other hand ([x]
will fail if the index does not exist. That means these fail:
['cat'][1]
['cat'][-2]
Your comprehension means "take all line
s that meet the following:
rstrip
them they are not empty (remember an empty string is NOT a digit)You might want this instead:
[line.rstrip() for line in f if not line.rstrip() or line.rstrip()[-1].isdigit()]
That will include your blank lines.
As a clarification, you are at no point getting values from outside of the string ''[-123:]
will pass. ''[-123]
(no colon) will fail.
Upvotes: 1
Reputation: 7920
There is no implicit concatenation, slices don't do that. Consider this example:
lines = ['', 'abc', 'xyz123']
for line in lines:
print repr(line.rstrip()[-1:]),
print line.rstrip()[-1:].isdigit()
Output:
'' False
'c' False
'3' True
The unexpected part might be how it handles the empty string. Any slice of the empty string will be an empty string because an out-of-bounds slice is an empty sequence. Then, str.isdigit
is defined to return False on empty strings, so these are filtered out from your list.
Upvotes: 1