【问题标题】:Defining a class inside a function to interrupt decorator execution在函数中定义一个类来中断装饰器的执行
【发布时间】:2019-04-15 21:22:09
【问题描述】:

我正在尝试在运行时配置装饰器。这与我之前的问题有些相关:How to configure a decorator in 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())

由于各种原因,我在使用装饰器时无法将其应用到类中。在我引用的问题中有一个简短的讨论。

【问题讨论】:

  • I'm trying to configure a decorator at run time. 他是个疯子

标签: python python-decorators


【解决方案1】:

虽然不是无效的,但通常不建议将类定义为函数内部的局部变量,因为这会使函数外部难以访问该类。

相反,您可以在函数外部定义类,并在实际需要时通过使用类对象调用装饰器函数将装饰器函数应用于该类:

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())

【讨论】:

  • 我很抱歉,但我已经尝试过这种方法,并且库出于某种原因不喜欢将装饰器应用于函数的技术。装饰器似乎没有“工作”,并且该类执行时就好像它不存在一样。在我的原始代码中,我真的不需要在我调用它的地方之外的类,但我也想用 Python 的方法做事,而不是把一些东西混在一起。
  • 我又试了一次,因为我认为它应该可以工作,我得到了这个异常:thespian.actors.InvalidActorSpecification: Invalid Actor Specification: <class 'calculator.calculator.Execute'> (module 'calculator.calculator' has no attribute 'Execute')....所以它说具有特定定义的类无效,然后它指向定义。显然我做错了什么。
  • 哦,对于任何偶然发现这一点的人。内联装饰器语法不能与 Thespian 剧团一起使用,因为根据 Thespian 作者的说法:“multiproc 系统库需要在单独的进程中执行实际创建,创建目标必须基于导入的结果和无法知道任何额外的本地计算。”
【解决方案2】:

actor_system 将要构建您的类的实例。这意味着它需要能够派生类对象——你不能在方法内部定义它。

如果你真的需要单独应用装饰器,你也许可以这样做

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

【讨论】:

  • 谢谢保罗。我从库作者那里得知,由于多处理的工作方式(对我来说有点陌生),将函数包装在装饰器中的内联方法被忽略了。我又回到了原点,但至少我现在知道为什么了。
猜你喜欢
  • 2015-10-23
  • 1970-01-01
  • 2021-04-06
  • 2012-02-06
  • 2012-04-11
  • 2021-12-12
  • 2016-07-25
  • 2017-08-11
相关资源
最近更新 更多