Claudiu B
Claudiu B

Reputation: 35

Two If Statements with a Logical Operator

I have the following code:

fhand=open('mbox-short.txt')
count=0
for line in fhand:
    words=line.split()
    print(words)
    if len(words)==0: continue
    if words[0]!='From': continue
    print(words[2])

This code prints a valid output (I am trying to get the day of a sent email from a mbox.txt file). When I try to combine the two "if" statements as follows:

if words[0]!='From' and len(words)==0: continue

I get this error:

['From', '[email protected]', 'Sat', 'Jan', '5', '09:14:16', '2008']
Sat
['Return-Path:', '<[email protected]>']
Traceback (most recent call last):
  File "untitled.py", line 7, in <module>
    print(words[2])
IndexError: list index out of range

I see that the issue occurs at the Return-Path line but why is it taken into consideration? And shouldn't the combined if statement have the same output as the two separated if statements?

Upvotes: 0

Views: 148

Answers (2)

glglgl
glglgl

Reputation: 91017

The differing output shows that the two solutions are not equivalent: you chose the wrong operator.

What happens in the original? If the fist condition is met, continue is executed. If not, the second one is tested and the loop continued as appropriate.

This behaviour is relicated by one operator. but this is the or operator. And if you do it in the right order, everthing works as wanted:

if len(words)==0 or words[0]!='From': continue

Let's look what happens: the first part of the condition is executed. If len(words)==0 is true, the second half is skipped (this is called short-circuiting) and the loop continued. This is good, as words[0] would lead to an error if evaluated despite the length being 0.

Only if the length is not 0, the second test is performed.

Note that there are several ways of testing a list for emptiness:

  • len(words) == 0
  • not len(words)
  • not words

Both of these expressions are True if the list is empty and False if not.

Upvotes: 2

SuperBiasedMan
SuperBiasedMan

Reputation: 9969

The issue you're having is that you flipped the order of your tests. You're now testing the length after attempting to check what the first value is:

if words[0]!='From' and len(words)==0: continue

Python checks conditions from left to right, so it will first check if words[0]!='From' and then test len(words)==0, however if words is empty then the first test tries to access a non existent index and creates your error.

You need to use this order instead and use the or operator as deceze pointed out, because you only care if one of these is True, not both.

if len(words)==0 or words[0]!='From': continue

Upvotes: 2

Related Questions