Расширить уже существующий объект в Python - PullRequest
0 голосов
/ 08 января 2020

Я пытаюсь продлить xml.ElementTree.Element. Проблема в том, что конструктор дает мне готовый экземпляр Element, который я не могу расширить без вмешательства в исходный код xml.

. Есть ли способ инициализировать класс, который наследуется от Element, и копировать все атрибуты Element в подкласс?

import xml.ElementTree as ET

root = ET.parse('file.xml').getroot() # retrieves Element instance

class ExtendedElement(ET.Element):
    def __init__(self, element):
        pass
        # somehow initialize the ExtendedElement instance
        # with all methods and attributes of element
        # without copying each attribute individually
        # ie self.attrib = element.attrib

    def custom_method(self):
        print(self.attrib)

ext = ExtendedElement(root)

ext.custom_method()

assert root.attrib == ext.attrib
assert list(ext) == list(root)

Обычно я просто go включаю и вызываю self.__dict__.update(element.__dict__), однако Element, похоже, не имеет __dict__ (как это даже возможный?).

Я хочу не копировать все атрибуты по отдельности, так как могу пропустить некоторые скрытые, не зная.

1 Ответ

1 голос
/ 08 января 2020

Как @CristiFati предложил в комментариях, вы должны использовать здесь композицию.

class ExtendedElement:
    def __init__(self, element):
        self.element = element

    def custom_method(self):
        print(self.element.attrib)

ext = ExtendedElement(root)
ext.custom_method()

Тогда 2 утверждения будут работать с правильным чередованием:

assert root.attrib == ext.element.attrib
assert list(ext.element) == list(root)

Если вам действительно нужно list(ext) на работу, тогда вы можете реализовать __iter__:

def __iter__(self):
    return iter(self.element)

, тогда второе утверждение будет работать следующим образом:

assert list(ext) == list(root)

В зависимости от ваших потребностей, вы можете взломать ExtendedElement чтобы раскрыть все атрибуты element, реализовав __getattr__:

def __getattr__(self, name):
    return getattr(self.element, name)

, тогда

ext = ExtendedElement(root)
print(ext.attrib)

выведет (с моим тестом. xml):

{'b': '1'}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...