Доступ к статическим полям из декорированного класса

Пример полного кода:

def decorator(class_):
    class Wrapper:
        def __init__(self, *args, **kwargs):
            self.instance = class_(*args, **kwargs)

        @classmethod
        def __getattr__(cls, attr):
            return getattr(class_, attr)
    return Wrapper


@decorator
class ClassTest:

    static_var = "some value"


class TestSomething:

    def test_decorator(self):
        print(ClassTest.static_var)
        assert True

При попытке выполнить тест, появляется ошибка:

test/test_Framework.py F
test/test_Framework.py:37 (TestSomething.test_decorator)
self = <test_Framework.TestSomething object at 0x10ce3ceb8>

    def test_decorator(self):
>       print(ClassTest.static_var)
E       AttributeError: type object 'Wrapper' has no attribute 'static_var'

Можно ли получить доступ к статическим полям из декорированного класса?

2 ответа

Решение

Хотя ответ @martineau, вероятно, лучше решает конкретную проблему, которую вы пытаетесь решить, более общий подход может заключаться в использовании метакласса для переопределения метода экземпляра. __getattr__ на type экземпляр (и классы являются экземплярами type).

def decorator(class_):
    class WrapperMeta(type):
        def __getattr__(self, attr):
            return getattr(class_, attr)

    class Wrapper(metaclass=WrapperMeta):
        def __init__(self, *args, **kwargs):
            self.instance = class_(*args, **kwargs)

    return Wrapper

Это позволяет просматривать атрибуты самого класса. WrapperMeta.__getattr__,

Вы можете заставить его работать, заставив декоратор создать класс, производный от декорируемого.

Вот что я имею в виду:

def decorator(class_):
    class Wrapper(class_):
        def __init__(self, *args, **kwargs):
            self.instance = super().__init__(*args, **kwargs)

    return Wrapper

@decorator
class ClassTest:
    static_var = "some value"

print(ClassTest.static_var)  # -> some value
Другие вопросы по тегам