Определение класса внутри функции для прерывания выполнения декоратора - PullRequest
2 голосов
/ 16 апреля 2019

Я пытаюсь настроить декоратор во время выполнения. Это в некоторой степени связано с моим предыдущим вопросом: Как настроить декоратор в Python

Мотивация для этого заключается в том, что я пытаюсь использовать код труппы Теспиана "как есть".

Законно ли иметь этот код здесь, где я определил класс (и потому назвал его декоратором) внутри метода класса? Опять же, причина этого в том, что я мог бы передать аргумент max_count до вызова декоратора.

Модуль является calculator.calculator (да, возможно, плохой выбор)

class Scheduler:
    def __init__(self):
        self.actor_system = None

    def start(self):
        self.actor_system = ActorSystem('multiprocTCPBase')

    def stop(self):
        self.actor_system.shutdown()

    def launch(self, count, func_and_data, status_cb):
        class CalcPayload:
            def __init__(self, func_and_data, status_cb):
                self.func_and_data = func_and_data
                self.status_cb = status_cb

        @troupe(max_count=count)
        class Execute(ActorTypeDispatcher):
            def receiveMsg_CalcPayload(self, msg, sender):
                func = msg.func_and_data['func']
                data = msg.func_and_data['data']
                status_cb = msg.status_cb

                self.send(sender, func(data, status_cb))

        exec_actor = self.actor_system.createActor(Execute)

        for index in range(len(func_and_data)):
            calc_config = CalcPayload(func_and_data[index], status_cb)
            self.actor_system.tell(exec_actor, calc_config)

        for index in range(len(func_and_data)):
            result = self.actor_system.listen(timeout)

        self.actor_system.tell(exec_actor, ActorExitRequest())

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

Ответы [ 2 ]

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

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

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

def launch(self, count, func_and_data, status_cb):
    wrapped = troupe(max_count=count)(Executor)
    exec_actor = self.actor_system.createActor(wrapped)
1 голос
/ 16 апреля 2019

Хотя это и недопустимо, обычно не рекомендуется определять класс как локальную переменную внутри функции, так как это затруднит доступ к классу вне функции.

Вместо этого вы можете определить классы вне функции и применить функцию декоратора к классу, когда это действительно необходимо, вызвав функцию декоратора с объектом класса:

class CalcPayload:
    def __init__(self, func_and_data, status_cb):
        self.func_and_data = func_and_data
        self.status_cb = status_cb


class Execute(ActorTypeDispatcher):
    def receiveMsg_CalcPayload(self, msg, sender):
        func = msg.func_and_data['func']
        data = msg.func_and_data['data']
        status_cb = msg.status_cb

        self.send(sender, func(data, status_cb))

class Scheduler:
    def __init__(self):
        self.actor_system = None

    def start(self):
        self.actor_system = ActorSystem('multiprocTCPBase')

    def stop(self):
        self.actor_system.shutdown()

    def launch(self, count, func_and_data, status_cb):
        exec_actor = self.actor_system.createActor(troupe(max_count=count)(Execute))

        for index in range(len(func_and_data)):
            calc_config = CalcPayload(func_and_data[index], status_cb)
            self.actor_system.tell(exec_actor, calc_config)

        for index in range(len(func_and_data)):
            result = self.actor_system.listen(timeout)

        self.actor_system.tell(exec_actor, ActorExitRequest())
...