[Tutor] re: Leap year problem

ahimsa ahimsa@onetel.net.uk
Tue Jan 14 16:50:11 2003


Hi Don
I know this is a bit belated, but dammit ... that work thing :-)

On Sun, 2003-01-12 at 21:32, Don Arnold wrote:

> The problem here is that the 'if ... elif ... else' construct exits as soon
> as one of its conditions is met. If year is divisible by 100, it satisfies
> the initial 'if' and falls through the rest of the structure, so you never
> get to the later tests. If you want to structure it like this, you have to
> start with the most specific test and work toward the more general ones:
> 
> def isLeapYear(year):
>     if year % 400 == 0:
>         return 1
>     elif year % 100 == 0:
>         return 0
>     elif year % 4 == 0:
>         return 1
>     else:
>         return 0
> 

OK - that makes sense to me, I thought by seeing if it divided by '100'
first it would eliminate it from going through the rest of the
conditions. Are there any quick and dirty guidelines about how one makes
those kinds of determinations when constructing conditional statements -
e.g. test large numbers first, or test for the rarely occurring variable
first, or ... ? I don't know how clear that question is. If it isn't
clear, let me know and I'll see if I can rephrase it. For instance, the
above guideline is, as you've stated, check initially for the specifics
of a case and then move to the more general. Would that apply in most
cases with a conditional suite?

> This implements the definition that Goncalo gave. To avoid having to order
> your tests from specific to general, you can eliminate the elif's by
> combining the conditions into a single one:
> 
> def isLeapYear2(year):
>     if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):
>         return 1
>     else:
>         return 0
> 

Actually arranging these all on a line is new to me (which shouldn't
come as a surprise considering that the whole language and endeavour is
new to me!!!), and I hadn't come across it in the books and tutorials I
have been reading ... probably just haven't gotten to that part yet. So,
just to deconstruct this part if I may ... because 'if' and 'and' and
'or' are keywords, the Python interpreter reads these the same *as if*
they were arranged in a vertical hierarchy, and also reads from right to
left? Because you have specified that '100 != 0' (which would be the
test to eliminate those years that do divide by 100 with no remainder),
the year entered must satisfy *all* of these criteria to return a
positive '1' value, or else will return a false '0' value. If the user
enters a nonyear (e.g. a string that cannot be divided), will the
failure of the input also be caught as a 0 or does one still need to add
an additional error catch to this? I suspect that 'else: return 0'
should be sufficient, but just want to confirm this.

> This is close to a word-for-word translation of the definition I gave, and
> (IMO) is easier to read. Either way, the net result is the same:
> 
> year = int(raw_input('year: '))
> while year != -1:
>     print 'isLeapYear :', isLeapYear(year)
>     print 'isLeapYear2:', isLeapYear2(year)
>     print ''
>     year = int(raw_input('year: '))
> 
> [begin script run]
> year: 2000
> isLeapYear : 1
> isLeapYear2: 1
> 
> year: 1900
> isLeapYear : 0
> isLeapYear2: 0
> 
> year: 1996
> isLeapYear : 1
> isLeapYear2: 1
> 
> year: 1997
> isLeapYear : 0
> isLeapYear2: 0
> 
> year: -1
> [end script run]
> 

This is a bit confusing, so I want to pick this apart too if you can
bear with me while I plod through this: These are my understandings line
by line, please steer me right if I'm going off track here.
line 1 => gets user input
line 2 => runs program on the proviso that a number >= 0 is entered at
input
thereafter you are testing both ways of writing the program given
specific years using '1' for yes it is a leap year and '0' for not.
The last line with '-1' stops the program because it violates the while
condition?


> Also, it's a good idea to explicitly return 0 for false. If you don't
> specify a return value, the function will return None. That works here, but
> one of Python's guiding principles is 'Explicit is better than implicit'.

Good point. Thanks.

> I think that's probably how most of us got started programming. If anything,
> I'd say it's fortunate, since you're studying this because you're interested
> in it, not just because someone is making you.

Well I am interested that's for sure, I'm sorry though if I'm being too
pedantic about all of this. I come from a psych and philosophy
background, and this really does require a different way of thinking, so
I am trying to retrain my brain.

> HTH,

It did - thank you :)

Andrew

-- 
ahimsa <ahimsa@onetel.net.uk>