Bharathi
Bharathi

Reputation: 1643

function dispatch in python with varying parameters

I have many records of the following type whose attribute values are in string

{
  "City": "Pune",
  "Temperature": "32",
  "Unit": "C",
  "Date": "22-11-2012"
}

and an associated record descriptor that defines datatype and other attribute properties

{
  "City": {
    "datatype": "string"
  },
  "Temperature": {
    "datatype": "double"
  },
  "Unit": {
    "datatype": "string"
  },
  "Date": {
    "datatype": "datetime",
    "dateformat": "%d-%m-%Y",
    "timezone": "UTC"
  }
}

I need to convert the record attribute values from string to the appropriate datatype mentioned in the record descriptor

I have a function dispatch dictionary

{
   "int" : string_to_int,
   "double": string_to_double,
   "bool": string_to_bool,
   "datetime": string_to_datetime
}

def string_to_int(value):
    <<convert to integer>>

def string_to_double(value):
    <<convert to double>>

def string_to_bool(value):
    <<convert to bool>>

def string_to_datetime(value, date_format, time_zone):
    <<convert to datetime>>

By looping through each attribute, how can I do a function dispatch in python to convert the attribute values to appropriate data types? What is the right way to pass additional arguments for datatime conversion without using any if..else logic within the loop?

Upvotes: 1

Views: 1223

Answers (1)

Matthew Story
Matthew Story

Reputation: 3783

To answer your specific question, if you modify your type name to function map to store the functions themselves, rather than the name of the function:

type_to_function_map = {
   "int" : string_to_int,
   "double": string_to_double,
   "bool": string_to_bool,
   "datetime": string_to_datetime
}

And you change the additional arguments to functions like string_datetime to be keyword arguments:

def string_to_datetime(value, date_format=None, time_zone=None):
    pass

You can easily write a function like:

def load(payload, schema)
    output = {}
    for k, v in payload.items():
        field_info = schema[k].copy()
        output[k] = type_to_function_map[field_info.pop("datatype")](v, **field_info)

    return output

But having said that, there are a number of libraries that do what you're trying to do far better. My personal favorite of these is marshmallow:

from marshmallow import fields, Schema

class MySchema(Schema):
    City = fields.String()
    Temperature = fields.Float()
    Unit = fields.String()
    Date = fields.DateTime("%d-%m-%Y")

Which you can then use like this:

MySchema().loads(data)

Upvotes: 5

Related Questions