[Tutor] How to type annotate complex dictionary containing lambdas?

Mats Wichmann mats at wichmann.us
Sun Nov 17 10:25:52 EST 2019


On 11/17/19 1:52 AM, Alan Gauld via Tutor wrote:
> On 17/11/2019 05:32, boB Stepp wrote:
>> My best effort so far to type annotate the dictionary below is to use
>> "Any" for the dictionary values.  Is there a better substitute for
>> "Any" that would more precisely type annotate these dictionary values?
> 
> To be honest I wouldn't even be trying I'd be more concerned with
> getting rid of such a messy dict and replacing it with a class.
> 
> Type hints are no substitute for clean code.

Indeed.  It turns out that classes are (normally) expressed as a dict, 
so there's not even that much to do to convert.

Here's a simple class definition that contains some of your dict, based 
on snipping a few lines and just changing the syntax, no attempt to make 
any logic changes:

class Foo():
     greeting_msg = "Please enter the date by which you wish to attain 
your goal.\n"
     input_prompt = "Enter year of your goal as an integer:  "
     date_value_err_ck = lambda goal_year: date(goal_year, 1, 1)
     err_msg = "That is not a valid year.  Please try again."

print(Foo.__dict__)

And when run the print gives you (I took the liberty of putting in line 
breaks for readability):

{'__module__': '__main__',
  'greeting_msg': 'Please enter the date by which you wish to attain 
your goal.\n',
  'input_prompt': 'Enter year of your goal as an integer:  ',
  'date_value_err_ck': <function Foo.<lambda> at 0x7f6f3d224c20>,
  'err_msg': 'That is not a valid year.  Please try again.',
  '__dict__': <attribute '__dict__' of 'Foo' objects>,
  '__weakref__': <attribute '__weakref__' of 'Foo' objects>,
  '__doc__': None}


look familiar?  :)   Python has added some special symbols as well but 
otherwise it's the same thing.  So the choice of "use a dict instead of 
a class definition because it's simpler" isn't actually always simpler, 
and here it isn't as you've ended up defining a list of tuples or 
lambdas. Like Alan, I shudder :). The keys in your dict are all strings, 
those would map directly to the attribute and method names in the class.

In addition, the general guideline is if you're going to give it a name, 
don't use a lamba, because it's no longer anonymous at that point, 
defeating the only purpose lambda actually has.  You've given the first 
lambda the name date_value_err_check, which means it's actually:

def date_value_err_ck(self, goal_year):
     return date(goal_year, 1, 1)

you'd probably expand that to do all the work of "conditons" (though we 
don't see the code to use it)

As you your actual question...

>> goal_year_params: Dict[str, Any] = {

the two types that the dict's values can be per your snip is str or 
list, so start there:

goal_year_params: Dict[str, Union(str, List)]

if you want to go further you can then specify what the list consists 
of, etc.

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



More information about the Tutor mailing list