2016-08-01 33 views
1

我目前正在复制类似于这个问题的东西:python switch by class name?鸭打字和异物

我有一个for循环,在一组对象进行迭代,并且对它们进行分类,按类型,分成几个列表中的一个。

for obj in list_of_things: 
    if isinstance(obj, Class1): 
     class1list.append(obj) 
    if isinstance(obj, Class2): 
     class2list.append(obj) 

等几个其他类。应用程序就像一个ORM - 每个类的数据将被提取并写入数据库,并且每个类都有不同的数据提取。此外,有必要在Class2的任何实例之前由ORM处理Class1的所有实例。最后,Class1和Class2不是我的 - 它们是我使用的API的输出,所以我没有能力像上一个问题中提到的那样改变它们(比如,编写一个serialize()方法来转储我在每个类中需要的数据)。我向API提出了一些对象的请求,并且使我得到了各种类型的对象,每个对象都需要提取不同的数据。

有没有更pythonic这样做?这种方法满足需要,但它伤害了我的眼睛,我想学习更好的方法。我对Python仍然很陌生。

回答

0

另一种方法,根据您的具体情况,可能会利用这样一个事实:type类型是不可变的,因此可以用作字典键。

所以,你可以这样做:

from collections import defaultdict 

list_of_things = [2, 3, "Some", "String"] 

obj_map = defaultdict(list)  
for obj in list_of_things: 
    obj_map[type(obj)].append(obj) 

print(obj_map) 

输出:

defaultdict(<type 'list'>, { 
    <type 'int'>: [2, 3], 
    <type 'str'>: ['Some', 'String'] 
}) 

这里的想法是,你不需要写一大堆if isinstance测试,你只是“组通过“每个对象的类型。

您可以通过使用类名作为键来访问字典的值:

print(obj_map[int]) # [2, 3] 
+0

我想到了这一点,但我的理解是,类型()不尊重子的关系,所以如果第3第三方API子类Class1但我想将这些子类作为Class1的实例对待,它将无法执行。现在,我碰巧知道没有我会得到的子类,但是我认为使用type()和isinstance()可以改变结果吗? –

+0

@JustinPalpant你是对的,子类*将被添加到不同的键下。你可以用'type(obj).__ bases__'做一些反省,但我只能看到变得越来越难看。然而,如果在不同的键下添加子类实例是可以接受的,你总是可以使用'issubclass()' – jedwards

+0

来提取给定类及其子类的实例。我不知道有关'issubclass()',它听起来像它可以填充最后的利基。我同意'type(obj).__ bases__'似乎可能会变得混乱。我打算将其标记为已接受。 –