lxml objectify не вызывает конструкторы для пользовательских классов элементов
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 />
Я хотел бы, чтобы это напечатало "Made CustomElement", но это не так. Могу ли я заставить его вызвать конструктор?
Как можно создать экземпляр класса CustomElement без вызова конструктора?
>>> isinstance(root,CustomElement)
True
1 ответ
От lxml
документы:
Инициализация элемента
Есть одна вещь, которую нужно знать заранее. Классы элементов не должны иметь
__init___
или же__new__
метод. Также не должно быть никакого внутреннего состояния, за исключением данных, хранящихся в базовом дереве XML. Экземпляры элементов создаются и мусор собирается при необходимости, поэтому невозможно предсказать, когда и как часто для них создается прокси. Еще хуже, когда__init__
вызывается метод, объект еще даже не инициализирован для представления тега XML, поэтому в предоставлении__init__
метод в подклассах.В большинстве случаев не требуется инициализация класса, поэтому вы можете довольствоваться переходом к следующему разделу. Однако, если вам действительно нужно настроить класс элементов при создании экземпляра, есть один из возможных способов сделать это. Классы ElementBase имеют
_init()
метод, который может быть переопределен. Его можно использовать для изменения дерева XML, например, для создания специальных дочерних элементов или проверки и обновления атрибутов.Семантика
_init()
являются следующими:
Он вызывается один раз во время создания класса Element. То есть, когда представление элемента в Python создается с помощью lxml. В это время объект элемента полностью инициализируется для представления конкретного элемента XML в дереве.
Метод имеет полный доступ к дереву XML. Модификации могут быть сделаны точно так же, как и в любом другом месте программы.
Представления элементов в Python могут создаваться несколько раз за время существования XML-элемента в базовом дереве C.
_init()
Код, предоставляемый подклассами, должен сам по себе особо заботиться о том, чтобы множественные исполнения были либо безвредными, либо чтобы им препятствовал какой-то флаг в дереве XML. Последнее может быть достигнуто путем изменения значения атрибута или путем удаления или добавления определенного дочернего узла, а затем проверки этого перед выполнением процесса инициализации.Любые исключения, поднятые в
_init()
будет распространяться через вызов API, который приведет к созданию элемента. Так что будьте осторожны с кодом, который вы пишете здесь, поскольку его исключения могут появляться в разных неожиданных местах.