在python中包装for循环

时间:2017-05-12 09:48:45

标签: python for-loop iterable

我想包装for循环的功能,以便使用它更直观。在我的情况下,我必须解析xml文件,如下所示:

<instance id="line-n.w8_047:15696:">
    <answer instance="line-n.w8_047:15696:" senseid="product" />
    <context> context1 </context>
</instance>

<instance id="line-n.w8_088:12441:">
    <answer instance="line-n.w8_088:12441:" senseid="product" />
    <context> another context</context>
</instance>

我为Instance写了一个类:

class Instance:
    def __init__(self, id, answer, context):
        self.id = id
        self.answer = answer
        self.context = context

我编写了下一个枚举实例的函数:

import xml.etree.ElementTree as ET
def enum_instances(file_path, action):
    for instance_xml in ET.parse(file_path).getroot().find('lexelt'):
        action(Instance(
            instance_xml.attrib['id'],
            instance_xml.find('answer').attrib['senseid'],
            instance_xml.find('context').text)
        )

action参数是使用Instance执行某些操作的回调,如下所示:

enum_instances('/path/to/xml', lambda instance: print(instance.context))

但它看起来有点奇怪,我希望它更直观,就像这样:

for instance in enum_instances(file_path):
    print(instance.context)

实现'iterable'功能的最佳方法是什么? 感谢

2 个答案:

答案 0 :(得分:3)

在这种情况下获胜的发电机。像

这样的东西
def enum_instances(file_path):
    for instance_xml in ET.parse(file_path).getroot().find('lexelt'):
        yield Instance(
            instance_xml.attrib['id'],
            instance_xml.find('answer').attrib['senseid'],
            instance_xml.find('context').text)

然后你可以准确地说出你的要求:

for instance in enum_instances(file_path):
    print(instance.context)

答案 1 :(得分:1)

不是将callable传递给你的函数,而是让它产生Instance,然后你可以得到你想要的行为,例如:

def enum_instances(file_path, action=None):
    for instance_xml in ET.parse(file_path).getroot().find('lexelt'):
        instance = Instance(
            instance_xml.attrib['id'],
            instance_xml.find('answer').attrib['senseid'],
            instance_xml.find('context').text)
        if action is not None:
            instance = action(instance)
        yield instance

在这种情况下 - 我已将[{1}}默认为action,但在None之前,您可以通过某种方式传递函数以某种方式改变instance如果需要的话。

然后:

yield