【问题标题】:Wrapping for loop in python在python中包装for循环
【发布时间】:2017-10-11 14:06:42
【问题描述】:

我想包装 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)

实现“可迭代”功能的最佳方式是什么? 谢谢

【问题讨论】:

  • 那么为什么不做你想做的事呢?不要调用行动...而是...yield实例...
  • 顺便说一句,那个 XML 文件不是 XML。必须有一个根。
  • @polkovnikov.ph 你说得对,我的 xml 有一个根目录和一个凌乱的结构,但我只放了问题的相关部分

标签: python for-loop iterable


【解决方案1】:

在这种情况下,获胜的发电机。类似的东西

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)

【讨论】:

    【解决方案2】:

    不要将可调用对象传递给你的函数,而是让它产生一个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
    

    在这种情况下 - 我已将 action 默认为 None,但如果需要,您可以在 yield 之前传递一个函数以某种方式改变 instance

    然后:

    for instance in enum_instances('some_file_path'):
        print(instance.context)
    

    【讨论】:

    • 我想你已经打败了我——在最后一行的text) 之后你有多余的括号吗?
    猜你喜欢
    • 2016-12-08
    • 1970-01-01
    • 2014-09-27
    • 2021-04-08
    • 1970-01-01
    • 1970-01-01
    • 2016-07-18
    • 2011-01-30
    • 2020-10-18
    相关资源
    最近更新 更多