3

I'm trying to develop a class that cleans a dictionary based on field types incorporated into the class init function.

Its structure is something like this, but it doesn't work right now, as I can't figure out how to get a variable from the class instance dynamically, and how to apply the function to each variable:

class Cleaner:
    def __init__(self):
        self.int_fields = ['field_1', 'field_2']
        self.float_fields = ['field_3', 'field_4']
        self.field_types = [('int_fields', int), ('float_fields', float)]

    def get_clean_dict(self, dict):
        cleaned_dict = {}
        for field_type in self.field_types:
            for field_name, transform_func in getattr(self, field_type):
                try:
                    cleaned_dict[field_name] = transform_func(dict.get(field_name))
                except Exception:
                    cleaned_dict[field_name] = None
        return cleaned_dict

Here's how I expect it to behave:


sample_dict = {
    'field_1': 234,
    'field_2': 'Invalid',
    'field_3': 45.32345,
    'field_4': 'Invalid'
}

cleaner_inst = Cleaner()

cleaned_dict = cleaner_inst.get_clean_dict(sample_dict)

cleaned_dict = {
    'field_1': int(234),
    'field_2': None,
    'field_3': float(45.32345),
    'field_4': None
}
3
  • What is your code actually doing that you aren't satisfied with? Commented Apr 17, 2020 at 15:26
  • @Josh it doesn't work right now! TypeError: getattr(): attribute name must be string Commented Apr 17, 2020 at 15:27
  • Sidenote: When you have a class with two methods, one of them being __init__, you have to ask yourself: Do I really need a class? To me, Cleaner looks awfully much like a function... Commented Apr 17, 2020 at 15:33

2 Answers 2

4

The issue seems to be in the line getting the transform_func. The values in field_types are tuples of name and transformer, but this tuple is used as a parameter to getattr instead of the name only:

def get_clean_dict(self, dict):
    cleaned_dict = {}
    # transform_func belongs to self.field_types
    for field_type, transform_func in self.field_types:
        for field_name in getattr(self, field_type):
            try:
                cleaned_dict[field_name] = transform_func(dict.get(field_name))
            except Exception:
                cleaned_dict[field_name] = None
    return cleaned_dict
Sign up to request clarification or add additional context in comments.

Comments

0

You can use a dict to map fields name to fields transformer class,

class Cleaner:
    _field_desire_type_map = {
        'field_1': int,
        'field_2': int,
        'field_3': float,
        'field_4': float
    }

    def get_clean_dict(self, _dict):
        cleaned_dict = {}

        for _key, _value in _dict.items():
            try:
                transform_func = self._field_desire_type_map.get(_key)
                cleaned_dict[_key] = transform_func(_value)
            except Exception:
                cleaned_dict[_key] = None

        return cleaned_dict

Input:

dirty_dict = {
    'field_1': 234,
    'field_2': 'Invalid',
    'field_3': 45.32345,
    'field_4': 'Invalid'
}

Cleaner().get_clean_dict(dirty_dict) 

Output:

{'field_1': 234, 'field_2': None, 'field_3': 45.32345, 'field_4': None}

Caution: Try not to use dict as a variable name, it'll cause some unpredictable exception due to conflict with dict python reserve name.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.