Сбросить переменную при использовании для цикла в Python - PullRequest
0 голосов
/ 01 февраля 2019

Я - относительно новый программист, использующий дерево элементов xml для итерации по XML-файлу данных о членах.Я перебираю членов для извлечения данных и распределения переменных по фамилии, имени и идентификатору.

Проблема, с которой я столкнулся, заключается в том, что если у одного из членов есть пропущенный элемент (в отличие от пропущенных данных внутри элемента), то мой текущий код поддерживает значение переменной из последней итерации (member).

Мои данные:

<?xml version='1.0' ?>
<members>
    <member>
        <field name="surname">
            <text>Smith</text>
        </field>
        <field name="firstname" type="text">
            <text>John</text>
        </field>
        <field name="id" type="text">
            <text>123</text>
        </field>
    </member>
        <member>
        <field name="surname" type="text">
            <text>Bloggs</text>
        </field>

<!--missing firstname element here -->

        <field name="id" type="text">
            <text>789</text>
        </field>
    </member>
    <member>
        <field name="surname" type="text">
            <text>Jones</text>
        </field>
        <field name="firstname" type="text">
            <text>Jane</text>
        </field>
        <field name="id" type="text">
            <text>456</text>
        </field>
    </member>
</members>

Мой код:

tree = ET.parse('mydata.xml')
root = tree.getroot()
y = root.findall('member')
for member in y:
    fields = member.findall("field")
    for field in fields:
        if field.get('name') == 'surname':
            surname = field.find('text').text
        if field.get('name') == 'firstname':
            firstname = field.find('text').text
        if field.get('name') == 'id':
            id = field.find('text').text

    print(surname, firstname, id)    

Желаемый вывод:

Smith John 123
Bloggs  789
Jones Jane 456

Фактический вывод, который показывает имя блоггсакак Джон, а не пустой:

Smith John 123
Bloggs John 789
Jones Jane 456

Я могу избежать этого, установив переменную фамилию, имя и идентификатор перед каждой итерацией члена:

for member in y:
    surname = ''
    firstname = ''
    id = ''

    fields = member.findall("field")
    for field in fields:
        if field.get('name') == 'surname':
            surname = field.find('text').text
        if field.get('name') == 'firstname':
            firstname = field.find('text').text
        if field.get('name') == 'id':
            id = field.find('text').text

    print(surname, firstname, id)

, которая дает желаемый результат:

Smith John 123
Bloggs  789
Jones Jane 456

Однако это выглядит как обходной путь - есть ли альтернативный, более питонический способ добиться этого?

Ответы [ 3 ]

0 голосов
/ 01 февраля 2019

То, что у вас есть, на самом деле вполне нормально и доступно для чтения.Но если вы действительно хотите, вы можете использовать троичное выражение

for member in y:
    fields = member.findall("field")
    for field in fields:
        surname = field.find('text').text if field.get('name') == 'surname' else ''
        firstname = field.find('text').text if field.get('name') == 'firstname' else ''
        id = field.find('text').text if field.get('name') == 'id' else ''

    print(surname, firstname, id)
0 голосов
/ 01 февраля 2019

Может быть, этого легче достичь, поместив данные в диктат, используя их понимание.Таким образом, диктовка всегда будет перезаписываться, даже если она полностью пуста, поскольку в элементе нет полей:

for member in root.findall("member"):
    data = {field.get("name") : field.find("text").text for field in member.findall("field")}
    print(
        data.get("surname", "(no surname"),
        data.get("firstname", "(no firstname)"),
        data.get("id", "(no id")
    )

=>

Smith John 123
Bloggs (no firstname) 789
Jones Jane 456
0 голосов
/ 01 февраля 2019

эти вещи, возможно, лучше изолированы для собственной функции.и да, вы должны сбросить их в первую очередь, когда вы хотите пустые поля

...