2
if month == 1 or 10:
    month1 = 0
if month == 2 or 3 or 11:
    month1 = 3
if month == 4 or 7:
    month1 = 6
if month == 5:
    month1 = 1
if month == 6:
    month1 = 4
if month == 8:
    month1 = 2
if month == 9 or 12:
    month1 = 5

This code always returns month1 equal to 5. I'm quite new at programming, what am I doing wrong? (I guess it involves the fact that 12 is the highest number, but == means equals right?)

martineau
  • 119,623
  • 25
  • 170
  • 301
HankSmackHood
  • 4,673
  • 7
  • 29
  • 30

6 Answers6

7

EDIT: I first gave the wrong reason why this is not working. As others have pointed out,

if month == 1 or 10:
    # ...

is equivalent to

if (month == 1) or 10:
    # ...

So ... always gets executed.

You could use

if month in (1, 10):
    month1 = 0

or even better

a = [0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5]
month1 = a[month - 1]

or

d = {1: 0, 2: 3, 3: 3, 4: 6, 5: 1, 6: 4,
     7: 6, 8: 2, 9: 5, 10: 0, 11: 3, 12: 5}
month1 = d[month]

instead.

Yet another way of getting the same result would be to use the datetime module:

from datetime import datetime
month1 = (datetime(2011, month, 1) - datetime(2011, 1, 1)).days % 7
Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • doesn't `1 or 10` evaluate to `1` since `1` evaluates to True? I was going to re-answer, but I figured an edit here would serve the purpose. I tested the above in a shell also, I'm fairly confident but don't want to change your answer just incase. – Josh Smeaton Feb 13 '11 at 20:49
  • Actually, I think you've got the precedence wrong: `month == 1 or 10` will never come out False, because even if month is not 1, 10 is truthy. Toy example: `"A" == "A" or "C"` yields True, `"A" == "B" or "C"` yields "C" – Ulrich Schwarz Feb 13 '11 at 20:52
  • @Ulrich: You are also right. Well, probably not my best day today :) – Sven Marnach Feb 13 '11 at 20:59
  • Don't worry, that happens. :) – Ulrich Schwarz Feb 14 '11 at 06:23
5

When you write:

if month == 9 or 12:
    month1 = 5

it actually means:

if (month == 9) or (12):
    month1 = 5

what you want to have is:

if (month == 9) or (month == 12):
    month1 = 5
Vladimir Keleshev
  • 13,753
  • 17
  • 64
  • 93
1

Also, I think you want elif instead of just if:

if month == 1 or month == 10:
    month1 = 0
elif month == 2 or month == 3 or month == 11:
    month1 = 3
elif month == 4 or month == 7:
    month1 = 6
elif month == 5:
    month1 = 1
elif month == 6:
    month1 = 4
elif month == 8:
    month1 = 2
elif month == 9 or month == 12:
    month1 = 5

If the first condition (month is 1 or 10) is true, it will jump over the others.

carl
  • 49,756
  • 17
  • 74
  • 82
1

Not quite what's being asked, but I'd suggest re-implementing that using a dict as a quick lookup table. Eg:

month_lut = {
    1  : 0,
    10 : 0,
    2  : 3,
    3  : 3,
   11  : 3,
    4  : 6, 
    7  : 6,
    # more ...
}

month1 = month_lut[month]

Not only does it look more intuitive (to me anyway), you get a KeyError exception (which can be handled properly) if month is invalid instead of failing silently and ending up with an undefined month1.

Shawn Chin
  • 84,080
  • 19
  • 162
  • 191
  • I explained the problem in this way, but I was wrong. Sorry for the confusion... – Sven Marnach Feb 13 '11 at 21:01
  • @Sven. True.. retracting my statement. – Shawn Chin Feb 13 '11 at 21:03
  • +1 for most elegant solution. Although others are more explanatory, this shows a good straightforward approach to the problem (if we assume there isn't a rule for the corresponding numbers, as it seems). – MattiaG Feb 13 '11 at 21:05
1

Two things:

  1. You are using independent ifs (if, if, if), so every one of them will be tried every time. If you used cascading ifs (if, elif, elif), you would always get back month1=0 because:

  2. Your comparisons are not what you think! 'month == 1 or 10' will always return either True or 10. if month is 1, then month==1 is True, then True or 10 is True, and the body of the if statement gets run. In every other case, month==1 is False, and False or 10 is 10, which is 'truthy', so the if statement gets run!

Hugh Bothwell
  • 55,315
  • 8
  • 84
  • 99
0

A note on how the python or operator works:

For an expression x or y:

In the case that x is True, the expression returns x. This makes intuitive sense when x is a boolean--if x is True it returns True. In the case that x is False, then y is returned. This makes intuitive sense when y is a boolean. If x is False and y is True, you get a value of True from your or expression.

However, things get trickier when either x is not a boolean, or x is False and y is not a boolean. In your case, month == 1 is a boolean. As in the rules above, when this is false, it returns the second half of the or expression. Since 10 is not a boolean, but an integer, it is simply returned.

The reason month1 always equals 5 is that in your last two lines you have such a problem. In your statement

if month == 9 or 12:

python first checks to see what the or statement returns. Here, it will either return True (if the month actually is 9) or if month is not nine, since 12 isn't a boolean, it will return 12. Both of these values (True and `12) cause the if statement to pass, and the line after it to be evaluated, setting month1 to 12.s

I would note that the other answers explain better approaches to this code. However, it is still useful to understand how Boolean Operators work in python.

Wilduck
  • 13,822
  • 10
  • 58
  • 90