【发布时间】:2018-12-02 23:42:57
【问题描述】:
我是装饰器的新手,但理想情况下,我想使用它们来简单地在类 OptionClass 中定义一堆类函数,每个函数代表一些带有名称和描述的特定选项,如果需要的话。如果有意义的话,我根本不想修改类函数的操作,我只想使用装饰器来定义名称、描述以及是否需要。
问题 1:我构造了一个 OptionClass(),我想将其称为 option_1。当我这样做时,我收到一个 TypeError,因为 call 装饰器没有接收到 OptionClass 的实例。为什么是这样?当我通过 OptionClass() 的实例调用 option_1 时,它可以工作。如何调用 option_1 而无需始终将实例作为 self 传递。 收到时的错误是:
Traceback (most recent call last):
File "D:/OneDrive_P/OneDrive/projects/python/examples/dec_ex.py", line 110, in <module>
print(a.option_1("test")) # TypeError: option1() missing 1 required positional argument: 'test_text'
File "D:/OneDrive_P/OneDrive/projects/python/examples/dec_ex.py", line 80, in __call__
return self.function_ptr(*args, **kwargs)
TypeError: option_1() missing 1 required positional argument: 'test_text'
问题 2:如何在装饰器上运行或调用方法来设置 set_name、set_description、set_required?
问题 3:虽然这是一个示例,但我打算使用异步函数编写选项类并装饰它们。我需要将装饰器 call 设置为 async def __call__() 还是因为它只是返回函数就可以了?
class option_decorator(object):
def __init__(self, function_pt):
self.function_ptr = function_pt
self.__required = True
self.__name = ""
self.__description = ""
def set_name(self, text):
self.__name = text
def set_description(self, text):
self.__description = text
def set_required(self,flag:bool):
self.__required = flag
def __bool__(self):
"""returns if required"""
return self.__required
def __call__(self, *args, **kwargs):
return self.function_ptr(*args, **kwargs)
def __str__(self):
"""prints a description and name of the option """
return "{} - {}".format(self.__name, self.__description)
class OptionClass(object):
"""defines a bunch of options"""
@option_decorator
def option_1(self,test_text):
return("option {}".format(test_text))
@option_decorator
def option_2(self):
print("option 2")
def get_all_required(self):
"""would return a list of option functions within the class that have their decorator required flag set to true"""
pass
def get_all_available(self):
"""would return all options regardless of required flag set"""
pass
def print_all_functions(self):
"""would call str(option_1) and print {} - {} for example"""
pass
a = OptionClass()
print(a.option_1("test")) # TypeError: option1() missing 1 required positional argument: 'test_text'
print(a.option_1(a,"test")) #Prints: option test
【问题讨论】:
-
请不要像这样使用双下划线名称修饰,Python != Java。每次你写一封信或二传手时,一条小蟒蛇都会死去。
-
无论如何,如果您发布完整的错误消息会很有帮助。我现在不在笔记本电脑旁,但是我怀疑您遇到了使用类装饰器装饰方法的常见问题-您的“方法”现在是装饰器类的实例,而不是函数类型的实例,因此它缺乏适当的描述符方法
__set__和__get__来实现方法实例绑定......通常,人们只是使用基于函数而不是基于类的装饰器来切断快活的结。使用闭包通常可以很好地处理状态。 -
从根本上说,我看不出你在这里使用装饰器的道理或理由。在我看来,您正在寻找简单的构图。
标签: python class asynchronous decorator