在Python中迭代字典列表并转换为对象



假设我有一个字典列表,比如:

list_of_dicts = [
    {'id': 'something', type: 'type_a', blah...},
    {'id': 'anotherthing', type: 'type_b', blah...},
    {'id': 'yetanotherthing', type: 'type_c', blah...},
    etc.
]

我有一些对象,比如:

class Base(object):
    def __init__(self, blah):
        self.blah = blah
class TypeA(Base):
class TypeB(Base):
class TypeC(Base):
etc.

我想迭代列表,然后根据条件,比如说:

for elem in list_of_dicts:
    if elem['type'] == 'type_a':
        my_obj = TypeA(blah)
    elif elem['type'] == 'type_b':
        my_obj = TypeB(blah)
    etc.

我可能有很多课。如何避免选择正确对象的漫长if/elif?有没有一种动态的方式来实现这一点?更好的是,我没有明确地为每种类型的对象选择和设置,这是不是太聪明了?

每个对象可能有10个以上的属性要设置,而这个if/elif块非常长,很难读取/维护。

更新:

更有可能的答案是,我完全错了。我最初的目标是拥有这个嵌套的dictionary,并希望以特定的方式"清理"/增强每个dictionary元素。也许对于一个具有'type'=='type_a'的元素,我想添加几个新键。如果'type'=='type_b',也许我想编辑一两个键的名称。如果'type'=='type_c',我想编辑某个键的值,等等。可能有30,40,可能有50种不同的类型。因此,我从一个"混乱"的嵌套dict开始,然后得到一个"干净"的dict,修改了我的方式。

我最初的方法是为每种类型都有一个类。然后,每个类都可以有自己的@property修饰方法,以特定的方式设置某些属性。它们都继承自同一个基类,该基类将有一个方法返回一个将所有属性作为键的字典。

一种方法是将类的名称直接包含在dicts列表中:

list_of_dicts = [
    {'id': 'something', 'class': TypeA, blah...},
    {'id': 'anotherthing', 'class': TypeB, blah...},
    {'id': 'yetanotherthing', 'class': TypeC, blah...},
    etc.
]
...
for elem in list_of_dicts:
    my_obj = elem['class'](attributes)

为了实现这一点,您必须在dict列表之前声明类。如果这不可能或不可取,你可以将它们与另一本词典联系起来。

classes = {'type_a': TypeA, 'type_b': TypeB, 'type_c': TypeC}
for elem in list_of_dicts:
    my_obj = classes[elem['type']](attributes)

然而,我没有发现您的原始代码有什么特别的错误,在某些方面,它比这些方法更容易阅读。

您可以使用这样的小class_factory函数:(我还改进了一点基类逻辑)

list_of_dicts = [
    {'id': 'something', 'type': 'type_a', 'name': 'batman'},
    {'id': 'anotherthing', 'type': 'type_b', 'city': 'NYC', 'country': 'USA'},
    {'id': 'yetanotherthing', 'type': 'type_c', 'foo': 'bar'},
    {'id': 'one with no type', 'best_city': 'Paris'},
    {'id': 'one with an unknown type', 'type': 'type_z', 'result': 'it still works'},
]
class Base(object):
    def __init__(self, **kwargs):
        kwargs.pop('type', None)
        for attr_name, attr_value in kwargs.items():
            setattr(self, attr_name, attr_value)
class TypeA(Base):
    pass
class TypeB(Base):
    pass
class TypeC(Base):
    pass

def class_factory(a_dict):
    mapping = {
        'type_a': TypeA,
        'type_b': TypeB,
        'type_c': TypeC,
    }
    return mapping.get(a_dict.get('type'), Base)

my_dynamic_objects = []
for elem in list_of_dicts:
    my_dynamic_objects.append(class_factory(elem)(**elem))

相关内容

  • 没有找到相关文章

最新更新