__getattr__ и __getattribute__ для классов / статических атрибутов динамически генерируемых классов - PullRequest
1 голос
/ 12 апреля 2019

Этот вопрос отвечает, как реализовать __getattr__ для статических / классовых атрибутов - с использованием метакласса.Тем не менее, я хотел бы реализовать __getattr__ и __getattribute__ для класса, сгенерированного type(), и, чтобы сделать вещи еще более интересными, класс наследует класс, который имеет собственный метакласс, который должен выполняться правильно.

Код, резюмирующий абзац выше:

class Inherited(metaclass=SomeFancyMetaclass):
    ...

generated_class = type("GeneratedClass", (Inherited,), {})

def __class_getattr__(cls, name):  # __getattr__ for class, not sure how the code shall look exactly like
    return getattr(cls, name)

setattr(generated_class, "__getattr__", __class_getattr__)  # similarly for __getattribute__

Вопрос: возможно ли это, и если да, то как?Может ли кто-нибудь привести минимальный рабочий пример?

1 Ответ

1 голос
/ 12 апреля 2019

Просто сделайте ваш метакласс наследуемым от SomeFancyMetaclass, правильно реализуйте __getattr____getattribute__) там и используйте этот метакласс, а не вызов type для генерации вашего унаследованного динамического класса.

Хотя вы используете много редко используемых вещей, на этом пути нет никаких специальных механизмов - это должен быть простой Python -

Конечно, вы не сказали что вы хотитечтобы делать в метаклассе специальные методы - там может быть какая-то чёрная магия - и если вы делаете __getattribute__, вы всегда должны быть очень осторожны и перенаправлять все атрибуты, которые вас не интересуют, в супер-call, иначе ничего не работает.

Кроме того, имейте в виду, что настройка доступа к атрибутам, возможная с обоими методами, не будет работать для «создания магических методов обработки» - то есть: ваш класс не будет магическиесть метод __add__ или __dir__, потому что ваш метакласс __getattribute__ генерирует один - точнее, они фиксируются в специальных слотах во время выполнения Python, иПроверка и вызов eir обходит обычный поиск атрибутов в Python.

В противном случае:

class Inherited(metaclass=SomeFancyMetaclass):
    ...

class MagicAttrsMeta(Inherited.__class__):
    def __getattr__(self, attr):
          if attr in ("flying", "circus", "brian", "king_arthur"):
               return "coconut"
          raise AttributeError()


generated_class = MagicAttrsMeta("GeneratedClass", (Inherited,), {})
...