假设我有一个词典列表,如:
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.
我可能会有很多课程。如果/ elif选择正确的对象,我该如何避免这个?有没有动态的方法来实现这一目标?更好的是,我是不是因为没有明确地为每种类型的对象选择和设置而过于聪明?
每个对象可能有10个以上的属性要设置,如果/ elif块非常长并且难以阅读/维护。
更新
更可能的答案是我完全错了。我最初的目标是我有这个嵌套字典,我想“清理它”/以特定方式增强每个字典元素。也许对于'type'=='type_a'的元素,我想添加几个新键。如果'type'=='type_b',也许我想编辑一两个键的名称。如果'type'=='type_c',我想编辑某个键的值等。可能有30,40个可能有50种不同的类型。所以我从一个“凌乱”的嵌套字典开始,然后回到一个“干净”的字体,修改我的方式。
我最初的方法是为每种类型设一个班级。然后每个类可以有自己的@property
装饰方法来以特定方式设置某些属性。它们都继承自相同的基类,该基类具有返回字典的方法,该字典将所有属性作为键。
答案 0 :(得分:0)
一种方法是直接在您的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)
要使其工作,您必须在dicts列表之前声明类。如果这不可能或不可取,您可以将它们与另一个字典链接。
classes = {'type_a': TypeA, 'type_b': TypeB, 'type_c': TypeC}
for elem in list_of_dicts:
my_obj = classes[elem['type']](attributes)
但是,我没有看到您原始代码的任何特别错误,这在某些方面比这些方法更容易阅读。
答案 1 :(得分:0)
你可以像这样使用一个小的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))