Цикл Python над ненаследуемыми атрибутами в базовом классе - PullRequest
0 голосов
/ 01 февраля 2019

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

class baseclass(object):
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

    def calcValue(self):
        return sum(vars(self).values())

Теперь у меня есть извлеченный класс из этого класса, которыйдобавляет дополнительные атрибуты к классу, например;

class childclass(baseclass):
    def __init__(self, stringValue, **kwargs):
        super(childclass, self).__init__(kwargs)
        self.name = stringValue

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

instance = childclass("myname", a=1, b=2, c=3)

, а затем вызываю метод calcValue, он должен вернуть 1 + 2 + 3 = 6

instance.calcValue()

, но так какvars (self) вернет полный словарь, исключая строку из атрибута childclass, который, конечно, затем не может быть добавлен.Есть ли способ получить доступ только к атрибутам экземпляра, принадлежащим соответствующему удаленному классу?

Ответы [ 2 ]

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

Простой, безопасный и эффективный, но с дополнительными издержками, - хранить атрибуты базового класса в отдельном атрибуте и использовать __getattr__ для их обслуживания:

class BaseClass(object):
    def __init__(self, **kwargs):
        self._attribs = kwargs

    def __getattr__(self, name):
        try:
            return self._attribs[name]
        except KeyError:
            raise AttributeError("object {} has no attribute {}".format(type(self).__name__, name))

    def calcValue(self):
        return sum(self._attribs.values())

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

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

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

В Python есть пара механизмов для обработки атрибутов особым образом.Если бы вы объявили атрибуты вашего базового класса в самом классе и просто инициировали их значения в методе __init__, можно было бы проанализировать базовый класс '__dict__ (а не экземпляр __dict__) экземпляра,или атрибут __annotations__ в том же классе.

Как и в примере, одной простой вещью является использование специального атрибута для отметки атрибутов, добавляемых в базовый класс, иЗатем вы обратитесь к источнику имени атрибутов:

class baseclass(object):
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)
        self._numeric_attrs = set(kwargs.keys())

    def calcValue(self):
        return sum(getattr(self, attr) for attr in self._numeric_attrs)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...