Search code examples
pythonpython-3.xfunctioncompiler-errorslocal-variables

Why is python giving me an unbound local error on introducing new variable inside function?


x = int(input("Enter the input in seconds "))

def checkSeconds(x):
    
    if x >= 86400:
        d = x/86400
        x = x%86400
        
    if x >= 3600:
        h = x/3600
        x = x%3600
        
    if x >= 60:
        m = x/60
        x = x%60
        
    s = x
    
    print(d, ":", h, ":" , m, ":", s)
    
checkSeconds(x)

Error : 'UnboundLocalError: local variable 'd' referenced before assignment'

Please bear with me since I am a beginner and still learning. It says 'local variable 'd' referenced before assignment'. Please let me know how to fix this error.


Solution

  • d, h and x require values even if their corresponding conditionals (if statements) aren't true.

    There's also a few more things I wanted to show you in an example.

    First thing I did was to convert to integers the quotients from the division operations. Otherwise in this code the hours, minutes, and seconds would also include the fractional parts that you actually want in the remainder.

    Second thing I did here was to take out the input call and replace it with several hard-coded values below. This way I don't have to input data over and over again, and instead a few simple test cases that can verify that the code is working for me. Lots of new programmers love using their keyboard to interact with running code. There's nothing wrong with that, and it's common in academia to require students to input values at runtime, maybe just to underscore the point that the behavior of the code is dynamic. But in the real world it's very unusual to actually prompt for interactive input to your programs, mostly because it's inconvenient and prone to data entry errors or inconsistencies. This is a point of opinion, and I just wanted to expose you to the consideration.

    Once I did that, I was able to define a few values which test out a few different scenarios.

    0: none of the conditions match 59: none of the conditions match 121: only the minutes condition matches 3662: hours, minutes, and seconds match. 882221: all units match.

    With those changes, we can now run the code and get out numbers we would like

    def checkSeconds(x):
        if x >= 86400:
            d = int(x/86400)
            x = x%86400
        else:
          d = 0
    
        if x >= 3600:
            h = int(x/3600)
            x = x%3600
        else:
          h = 0
    
        if x >= 60:
            m = int(x/60)
            x = x%60
        else:
          m = 0
    
        s = x
    
        print(d, ":", h, ":" , m, ":", s)
    
    for x in [ 0, 59, 121, 3662, 882221 ]:
      checkSeconds(x)
    

    And since I hard coded the test cases, it's easy to make my results reproducible.

    $ python3 ./t.py
    0 : 0 : 0 : 0
    0 : 0 : 0 : 59
    0 : 0 : 2 : 1
    0 : 1 : 1 : 2
    10 : 5 : 3 : 41