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

Cameron Simpson cs at cskk.id.au
Sun Mar 24 18:04:21 EDT 2019


On 24Mar2019 14:33, boB Stepp <robertvstepp at gmail.com> wrote:
>> On 23Mar2019 22:15, boB Stepp <robertvstepp at gmail.com> wrote:
>>
>> The lambda is just a single line function definition, and doesn't get a
>> function name.
>
>> So your get_input name now accepts a "date_constructor" parameter and
>> you would change the input step from this:
>>
>>     try:
>>         identifier = int(input(input_prompt))
>>         if date_value_err_ck:
>>             date(*date_value_err_ck)
>>     except ValueError:
>>
>> to this:
>>
>>     try:
>>         value = int(input(input_prompt))
>>         date = date_constructor(value)
>>     except ValueError:
>
>You could not know this from the code I showed (As I pared it down to
>illustrate my problem.), but I am also using get_input() to pull in
>from the user non-date values, too, but they are also all integers:
>pages_read and total_pages_to_read.  Because of this, for these latter
>two items, "date_value_err_ck" will be assigned "None", which is why I
>have the "if date_value_err_ck:".

Ok. So I realised later that you're not using the date from 
date_constructor; you're just calling it to see if it raises ValueError 
as a sanity check.

Why not make that a condition, and drop date_value_err_ck altogether?

    'conditions': [
        (lambda goal_year: datetime.date(goal_year, 1, 1),
            "This doesn't look like a valid date year to datetime.date()."),


and make the condition checking code more robust:

    for bad_condition, message in conditions:
        try:
            badness = bad_condition(input_value)
        except ValueError as e:
            print("Invalid goal_year, cannot even run the condition check! " + str(e))
        else:
            if badness:
                print(message)

That reduces your opening try/except to just checking that the input is 
a valid int, a lot simpler.

>> Well, when you define the goal_month constructor lambda function,
>> goal_year _is_ a local variable. And _because_ it is not a parameter of
>> the lambda, the lambda finds it in the scope where it was defined: the
>> scope at the bottom of your programme.
>>
>> This is called a "closure": functions has access to the scope they are
>> define in for identifiers not locally defined (eg in the parameters or
>> the function local variables - which are those assigned to in the code).
>
>This is so cool and useful!  I recall seeing this mentioned for nested
>functions, but did not know it worked for lambdas as well.

Lambda are functions. Same rules.

Cheers,
Cameron Simpson <cs at cskk.id.au>


More information about the Tutor mailing list