我正在写一些代码,我有一个字典,其中键是任何字符串,值是一个函数。然后我循环遍历字典中的每个键并调用函数,如下所示:
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
我怎么能这样做。帮助赞赏。
我不认为这是可能的。
首先,您应该阅读: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
会更容易。
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()