lxml objectify не вызывает конструкторы для пользовательских классов элементов. - PullRequest
1 голос
/ 21 декабря 2010

lxml.objectify, похоже, не вызывает конструкторы для моих пользовательских классов элементов:

from lxml import objectify, etree

class CustomLookup(etree.CustomElementClassLookup):
    def lookup(self, node_type, document, namespace, name):
        lookupmap = { 'custom' : CustomElement }
        try:
            return lookupmap[name]
        except KeyError:
            return None

class CustomElement(etree.ElementBase):
    def __init__(self):
        print("Made CustomElement")

parser = objectify.makeparser()
parser.set_element_class_lookup(CustomLookup())
root = objectify.parse(fname,parser).getroot()

Предположим, файл для анализа

<custom />

Я бы хотел, чтобы это распечатать "Сделано CustomElement ", но это не так.Можно ли заставить его вызывать конструктор?

Как создать экземпляр класса CustomElement без вызова конструктора?

>>> isinstance(root,CustomElement)
True

1 Ответ

2 голосов
/ 21 декабря 2010

Из lxml документов :

Инициализация элемента

Есть одна вещь, которую нужно знать заранее. Классы элементов не должны иметь __init___ или __new__ метод. Там не должно быть никакого внутреннего состояния либо, кроме данных, хранящихся в базовое дерево XML. Элемент экземпляры создаются и мусор собирать по необходимости, поэтому нет возможности предсказать, когда и как часто прокси создан для них. Еще хуже, когда метод __init__ вызывается, объект еще даже не инициализирован представляют тег XML, поэтому нет много пользы в предоставлении __init__ метод в подклассах.

Большинство случаев использования не потребует никакого класса инициализация, так что вы можете контент себя с пропуском к следующему раздел на данный момент. Однако если вы действительно нужно настроить свой элемент класс по инстанции, есть один Возможный способ сделать это. ElementBase классы имеют метод _init(), который может быть отменено Это может быть использовано для изменить дерево XML, например, строить специальные дети или проверить и обновить атрибутов.

Семантика _init() являются следующими:

  • Вызывается один раз на Время создания класса элемента. Тот когда Python представляет элемент создан lxml. В в этот раз объект элемента полностью инициализирован для представления определенный элемент XML в дереве.

  • Метод имеет полный доступ к XML дерево. Модификации могут быть сделаны в точно так же, как и везде в программе.

  • Представления Python элементов может быть создано несколько раз в течение жизни XML элемент в базовом C-дереве. _init() код, предоставляемый подклассами, должен заботиться о том, чтобы несколько казней либо безвредны или что они предотвращены какой-то флаг в дереве XML. последнее может быть достигнуто путем изменения Значение атрибута или путем удаления или добавление определенного дочернего узла, а затем проверяя это, прежде чем пробежать процесс инициализации.

  • Любые исключения поднятый в _init() будет размножен через вызов API, который приводит к создание Элемента. Так что будьте осторожны с кодом, который вы пишете здесь, как его исключения могут появляться в различных неожиданные места.

...