Как реализовать функциональность, зависящую от экземпляра, используя декоратор родительского класса? - PullRequest
0 голосов
/ 07 декабря 2018

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


Родитель метод

Если give_feedback - статический метод, в методе нет self.Но если это метод экземпляра, в пространстве имен, в котором он применяется, нет self.

class Interface:
    def __init__(self, quiet=False):
        self.quiet = quiet

    def echo(self, text):
        if not self.quiet:
            print(text)

    def give_feedback(self, func):
        def wrapper(*args):
            print('Calling give_feedback.')
            self.echo(func(*args))
        return wrapper

class App(Interface):
    @Interface.give_feedback  # self not defined here.
    def app_func(self, num):
        feedback = 'Success with {num}'.format(num=num)
        return feedback

if __name__ == '__main__':
    a = App()
    a.app_func(3)

Parent class с использованием __call __ (cf. link example_1)

Невозможно получить доступ к объекту из __call__.

class Interface:
    # ...

    class give_feedback:
        def __init__(self, func):
            self.func = func

        def __call__(self, *args):
            print(
                'Calling {func}'.format(func=self.func)
            )
            instance = get_obj_instance(self.func)  # What is this?
            return instance.echo(self.func(instance, *args))

class App(Interface):
    # ...

if __name__ == '__main__':
    # ...

Родительский дескриптор (ср.. link example_2)

Может получить доступ к объекту, но без аргументов.

class Interface:
    # ...

    class give_feedback:
        # ...

        def __get__(self, instance, owner):
            print(
                'Getting {func} from {inst} of {ownr}'.format(
                    func=self.func, inst=instance, ownr=owner
                )
            )
            num = 2  # How to get num???
            return instance.echo(self.func(instance, num))

class App(Interface):
    # ...

if __name__ == '__main__':
    a = App()
    a.app_func  # No ability to pass parameters.

Есть ли хороший способ сделать это?

1 Ответ

0 голосов
/ 08 декабря 2018

Почему бы не объединить 2-й и 3-й методы?Используйте __get__, чтобы получить экземпляр класса, и __call__, чтобы украсить echo.Вместо возврата app_func верните новый объект, который содержит экземпляр и имеет желаемое поведение __call__.

class Interface:
    def __init__(self, quiet=False):
        self.quiet = quiet

    def echo(self, text):
        if not self.quiet:
            print(text)

    class give_feedback:
        def __init__(self, func):
            self.func = func

        def __get__(self, instance, owner):
            return self.InstHolder(instance, self.func)

        class InstHolder:
            def __init__(self, inst, func):
                self.inst = inst
                self.func = func

            def __call__(self, *args):
                return self.inst.echo(self.func(self.inst, *args))


class App(Interface):
    @Interface.give_feedback
    def app_func(self, num):
        feedback = 'Success with {num}'.format(num=num)
        return feedback


if __name__ == '__main__':
    a = App()
    a.app_func(3)
    a.quiet = True
    a.app_func(4)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...