Saraverflow
Saraverflow

Reputation: 25

local variable referenced before assignment, I can't figure out why this is popping out

These are the instructions: In the Gregorian calendar, three conditions are used to identify leap years:

The year can be evenly divided by 4, is a leap year, unless: The year can be evenly divided by 100, it is NOT a leap year, unless: The year is also evenly divisible by 400. Then it is a leap year.

So I'm writing this code, which needs to be given a year and if the year is a multiple of 4 and 400 it is a leap year. If it is a multiple of 100 it is not:

def is_leap(year):
    k = 400 % year
    m = 4 % year
    p = 100 % year
    if m == 0:
        if p == 0:
            if k == 0:
                leap = True
            else:
                leap = False
    return leap

year = int(input())
print(is_leap(year))

And this is the error message: UnboundLocalError: local variable 'leap' referenced before assignment

I can't figure out why isn't working, leap isn't being used anywhere except for inside the loop

Upvotes: 1

Views: 278

Answers (4)

gph
gph

Reputation: 1361

You just need to define leap so that it exists when the execution doesn't make it to your innermost block.

def is_leap(year):
    k = 400 % year
    m = 4 % year
    p = 100 % year
    leap = False
    if m == 0:
        if p == 0:
            if k == 0:
                leap = True
    return leap

year = int(input())
print(is_leap(year))

Edit:

As others have correctly pointed out there are are some other problems with the code. In my experience date logic is much trickier than one would expect so instead of trying to roll your own I'd recommend using this:

import calendar
calendar.isleap(year)

Calendar documentation

Upvotes: 1

azro
azro

Reputation: 54148

There is many mistakes in your code

  • 400 % year should be year % 400, same for 4 and 100
  • you may defined leap before the if, for the case you're not entering the if and so not defining it later

More important your definition of leap year is wrong, your algorithm is wrong about it

def is_leap(year):
    m = year % 4
    p = year % 100
    k = year % 400
    leap = False
    if m == 0:  # should be multiple of 4
        leap = True
        if p == 0:  # exception if multiple of 100 : no leap
            leap = False
            if k == 0:  # exception if multiple of 400 : leap
                leap = True
    return leap

If you re-order the condition, you can avoid nesting them

def leapyr(n):
    if n % 400 == 0:
        return True
    if n % 100 == 0:
        return False
    if n % 4 == 0:
        return True
    return False

Upvotes: 0

Dawid Stec
Dawid Stec

Reputation: 11

If m or p is not equal to 0 then you are returning variable that was not initialized. You can set leap=False before first if, and completely delete else statement, and code will work as you probably want to.

Upvotes: 0

SumranMS
SumranMS

Reputation: 3

You should initialize leap variable before assigning it any value. That is what the problem is in my opinion. This is how the code should be

def is_leap(year):
    leap = False
    k = 400 % year
    m = 4 % year
    p = 100 % year
    leap = False
    if m == 0:
        if p == 0:
            if k == 0:
                leap = True
            else:
                leap = False
    return leap

year = int(input())
print(is_leap(year))

Upvotes: 0

Related Questions