简体   繁体   English

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

[英]Iterating a list of dictionaries and converting to objects in Python

Let's say I have a list of dictionaries like: 假设我有一个类似的字典列表:

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

And I have some objects like: 我有一些对象,例如:

class Base(object):
    def __init__(self, blah):
        self.blah = blah

class TypeA(Base):

class TypeB(Base):

class TypeC(Base):

etc.

I want to iterate over the list and then depending on a condition, let's say: 我想遍历该列表,然后根据条件,例如:

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.

I might have many classes. 我可能有很多课。 How do I avoid this really long if/elif of choosing the right object? 如果选择了正确的对象,如何避免这么长的时间? Is there a dynamic way to achieve this? 有没有动态的方法来实现这一目标? Better yet, am I trying to be too clever by not explicitly choosing and setting for every type of object? 更好的是,是否通过不为每种类型的对象明确选择和设置而变得过于机灵?

Each object may have 10+ attributes to set and this if/elif block is incredibly long and getting difficult to read/maintain. 每个对象可能要设置10多个属性,并且这个if / elif块非常长,并且难以读取/维护。

UPDATE: 更新:

The more than likely answer is that I am going about this totally wrong. 更有可能的答案是,我将完全犯错。 My original goal is that I have this nested dictionary and I want to "clean it up"/enhance each dictionary element a particular way. 我的最初目标是拥有这个嵌套的字典,我想以某种特殊方式“清理” /增强每个字典元素。 Maybe for an element with 'type'=='type_a', I want to add a couple of new keys. 也许对于带有'type'=='type_a'的元素,我想添加几个新键。 If 'type'=='type_b', maybe I want to edit the name of a key or two. 如果'type'=='type_b',也许我想编辑一个或两个键的名称。 If 'type'=='type_c', I want to edit the value of a certain key, etc. There could be 30,40 maybe 50 different types. 如果'type'=='type_c',我想编辑某个键的值,依此类推。可能有30,40种,也许有50种不同的类型。 So I start with a "messy" nested dict and get back a "clean" one, modified my way. 因此,我从“杂乱”的嵌套字典开始,然后返回“干净”的字典,修改了我的方式。

My original approach was to have a class for each type. 我最初的方法是为每种类型设置一个类。 And then each class could have their own @property decorated methods to set certain attributes a particular way. 然后,每个类可以具有自己的@property装饰方法,以特定方式设置某些属性。 And they all inherit from the same base class which would have a method that returns a dictionary with all the attributes as keys. 它们都继承自同一个基类,该基类将具有一个方法,该方法返回以所有属性为键的字典。

One approach would be to include the names of the classes directly in your list of 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)

For this to work you would have to declare the classes before the list of dicts. 为此,您必须在字典列表之前声明类。 If that's not possible or desirable you can link them with another dictionary. 如果这是不可能或不希望的,则可以将它们与另一本词典链接。

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

However I don't see anything particularly wrong with your original code, which is in some ways easier to read than these approaches. 但是,我没有发现原始代码有什么特别的问题,在某些方面,这些原始方法比这些方法更容易阅读。

You could just use a small class_factory function like this: (I also improved a bit the base class logic) 您可以只使用一个小的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))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM