在类方法中使用装饰器并填充变量

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

我正在写一些代码,我有一个字典,其中键是任何字符串,值是一个函数。然后我循环遍历字典中的每个键并调用函数,如下所示:

class SomeClass:

    dictionary = {}

    # Not sure how to use this decorator function
    def decorator(key):
        def wrapper(funct):
            self.dictionary[key] = funct
            return funct
        return wrapper


    @decorator("some_val1")
    def function_1(self):
       ...

    @decorator("some_val2")
    def function_2(self):
       ...

    @decorator("some_val3")
    def function_3(self):
       ...

    def execute_all_functions(self):
        for key, _ in self.dictionary.items():
            self.dictionary[key]()


if __name__ == "__main__":
    sclass = SomeClass()
    sclass.execute_all_functions()

所以这应该填充dictionary

{
   "some_val1": function_1(),
   "some_val2": function_2(),
   "some_val3": function_3()
}

我收到这个错误了

self.dictionary[key] = funct
NameError: name 'self' is not defined

我怎么能这样做。帮助赞赏。

python python-3.x
2个回答
0
投票

我不认为这是可能的。

首先,您应该阅读:https://docs.python.org/3.3/howto/descriptor.html,了解功能与方法的区别。

在您的代码中,键等于方法的self

def decorator(key):
    def wrapper(funct):
        self.dictionary[key] = funct
        return funct
    return wrapper

如果你想使用一个类的属性,你应该引用cls。正确的代码可能是:

@classmethod
def decorator(cls, key):
    def wrapper(funct):
        self.dictionary[key] = funct
        return funct
    return wrapper

因此,假设您要更新类属性,则必须具有cls引用。我已经尝试了下面的代码,使decorator_maker成为一种类方法。

class SomeClass:

    dictionary = {}

    @classmethod
    def decorator_maker(cls, key):
        print(cls, key)
        def decorator(funct):
            cls.dictionary[key] = funct
            return funct
        return decorator

    @decorator_maker("some_val1")
    def function_1(self):
       ...

    @decorator_maker("some_val2")
    def function_2(self):
       ...

    @decorator_maker("some_val3")
    def function_3(self):
       ...

    def execute_all_functions(self):
        for key, _ in self.dictionary.items():
            self.dictionary[key]()

你会得到像TypeError: 'classmethod' object is not callable这样的错误。与这个问题相同:'classmethod' object is not callable。 AKA,在定义类之前,不能调用类方法。

所以你可能想让装饰者在课外。但出于同样的原因,你不能得到cls的参考,直到classmethod。 method也是类的属性,在定义另一个属性时不能动态更改属性。见Python class method run when another method is invoked

如果你在课堂外移动dictionary会更容易。


0
投票

functools.wraps可能有用。在下面这个简单的例子中,没有wraps,装饰器将无法正常工作。

from functools import wraps

class SomeClass:
    var = 1

    @wraps
    def decorator(self, fn):
        return fn

    @decorator
    def return_value(self):
        print(self.var)
        return self.var


if __name__ == "__main__":
    sclass = SomeClass()
    sclass.return_value()
© www.soinside.com 2019 - 2024. All rights reserved.