[Tutor] How to avoid "UnboundLocalError: local variable 'goal_year' referenced before assignment"?

boB Stepp robertvstepp at gmail.com
Sat Mar 23 23:15:22 EDT 2019


I have just written a small program earlier today to allow the user
(me) to enter a date by which I wish to finish reading a book (=
massive programming-related book) and calculate how many pages I need
to read each day (starting today) in order to finish the book by the
target date.  Looking over my code I found that I was repeating a
fairly regular pattern in collecting the user input, so I thought I
would *improve* my working program by removing the duplicated code
into a single function.  So I came up with:

from datetime import date

def get_input(greeting_msg, identifier, input_prompt, date_value_err_ck,
        err_msg, conditions):
    """ ??? """

    if greeting_msg:
        print(greeting_msg)

    while True:
        try:
            identifier = int(input(input_prompt))
            if date_value_err_ck:
                date(*date_value_err_ck)
        except ValueError:
            print(err_msg)
            continue
        for (condition, condition_msg) in conditions:
            if condition:
                print(condition_msg)
                break
        else:
            return identifier

When I attempt to use this function with:

goal_year_params = {
            'greeting_msg': "Please enter the date by which you wish to attain"
                " your goal.\n",
            'identifier': 'goal_year',
            'input_prompt': "Enter year of your goal as an integer:  ",
            'date_value_err_ck': (goal_year, 1, 1),
            'err_msg': "That is not a valid year.  Please try again.",
            'conditions': [
                ('goal_year < date.today().year',
                    "Have you invented a time machine?  If not, please enter a"
                    " year that makes more sense!"),
                ('goal_year >= date.today().year + 100',
                    "Have you discovered the secret to eternal life?  And how"
                    " long is this book anyway?  Please enter a year that"
                    " makes more sense.")]}
goal_year = get_input(**goal_year_params)

I get the following traceback:

Traceback (most recent call last):
  File "pages_per_day.py", line 250, in <module>
    start_pgm()
  File "pages_per_day.py", line 246, in start_pgm
    goal_date_obj, pages_read, total_pages_to_read = get_inputs()
  File "pages_per_day.py", line 63, in get_inputs
    'date_value_err_ck': (goal_year, 1, 1),
UnboundLocalError: local variable 'goal_year' referenced before assignment

I understand this result, but cannot come up with a way to implement
my desired DRY strategy as I am stuck on how to get around this "local
variable ... referenced before assignment" issue.  On subsequent
passes "goal_year" will become "goal_month" and then "goal_day" as the
user needs to input all three of these numbers.  Is there a way to
accomplish my goal or am I attempting to be too clever?

-- 
boB


More information about the Tutor mailing list