在赋值方法中赋值之前引用的局部变量

问题描述 投票:2回答:1

我正在创建一个装饰器,可以让我做的事情:

@cooldownf(lambda self, **eargs: 30 - self.level)
def method(self, **eargs):
    ...

这将简单地装饰方法,使其具有冷却时间。这一切都运行得很好,现在可以每隔30 - self.level秒执行该方法。

但是,如果方法仍处于冷却状态,我想添加一条消息。我为message装饰器添加了一个cooldownf参数,但后来我在装饰器的代码中从UnboundLocalError: local variable 'message' referenced before assignment行得到了一个错误ìf message:

def cooldownf(fn, message=None):
    """Decorates a method to have a dynamic cooldown.

    Decorator function for easily adding cooldown as a dynamic time
    (function) into skill's methods. The function gets called when the
    cooldown is needed, and the skill is passed to the function.

    Args:
        fn: Function to determine the cooldown of the method
        message: Optional message sent if there's still cooldown left

    Returns:
        Decorated method with a dynamic cooldown
    """

    # Create a decorator using the function and message provided
    def method_decorator(method):

        # Create a wrapper method
        @wraps(method, assigned=WRAPPER_ASSIGNMENTS+('__dict__',), updated=())
        def method_wrapper(self, **eargs):

            # If the method's cooldown is over
            if method_wrapper.cooldown.remaining <= 0:

                # Restart the cooldown
                method_wrapper.cooldown.start(1, fn(self, **eargs))

                # And call the function
                return method(self, **eargs)

            # If there was cooldown remaining and a message is provided
            if message:

                # Format the provided message
                message = message.format(
                    name=self.name,
                    cd=method_wrapper.cooldown.remaining,
                    max_cd=method_wrapper.cooldown.limit
                )

                # Send it to the player
                SayText2(message=message).send(eargs['player'].index)

                # And exit with code 3
                return 3

        # Create the cooldown object for the wrapper
        method_wrapper.cooldown = TickRepeat(lambda: None)

        # And return the wrapper
        return method_wrapper

    # Return the decorator
    return method_decorator

是什么导致了这个?我可以在messagecooldownf内打印method_decorator,但在method_wrapper中添加打印将导致错误提升。这是确切的代码,我无法在IDLE中使用函数复制它,是否与我使用特定方法有关?

python python-3.x decorator python-decorators
1个回答
3
投票

您将在最里面的函数中分配method

message = message.format(
    name=self.name,
    cd=method_wrapper.cooldown.remaining,
    max_cd=method_wrapper.cooldown.limit
)

该赋值使其成为局部变量,但如果没有首先访问message,则无法进行该赋值。你不能用当地人做到这一点。

由于您不想修改已关闭的参数,因此您希望在此处使用新的本地名称:

formatted_message = message.format(
    name=self.name,
    cd=method_wrapper.cooldown.remaining,
    max_cd=method_wrapper.cooldown.limit
)
SayText2(message=formatted_message).send(eargs['player'].index)
© www.soinside.com 2019 - 2024. All rights reserved.