代码之家  ›  专栏  ›  技术社区  ›  user8716936

在python中将self传递给类装饰器的问题

  •  0
  • user8716936  · 技术社区  · 6 年前

    我对decorators还不熟悉,但理想情况下,我希望使用它们在类option class中简单地定义一组类函数,每个函数都用名称和描述表示一些特定的选项,如果需要的话。如果有意义的话,我根本不想修改类函数的操作,我只想使用decorator来定义名称、描述以及是否需要它。

    呼叫 decorator未接收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:如何在decorator上运行或调用方法以设置名称、设置描述、设置必需项?

    问题3:虽然这是一个示例,但我打算使用异步函数编写选项类并修饰它们。我需要做装饰工吗 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
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   gilch    6 年前

    问题1

    您将方法包装器实现为可自定义调用的,而不是普通的函数对象。这意味着您必须实现 __get__() 自己将函数转换为方法的描述符。(如果您使用了一个函数,则它已经存在。)

    from types import MethodType
    
    
    class Dec:
     def __init__(self, f):
         self.f = f
    
     def __call__(self, *a, **kw):
         return self.f(*a, **kw)
    
     def __get__(self, obj, objtype=None):
         return self if obj is None else MethodType(self, obj)
    
    
    class Foo:
        @Dec
        def opt1(self, text):
            return 'foo' + text
    

    >>> Foo().opt1('two')
    'footwo'
    

    Descriptor HowTo Guide

    问题2

    可赎回的 option_decorator 实例替换 OptionClass 这意味着改变可调用实例会影响 光学类 使用可调用对象的。确保这是您想要做的,因为如果您想要定制每个实例的方法,您将不得不以不同的方式构建它。

    class OptionClass(object):
        """defines a bunch of options"""
        @option_decorator
        def option_1(self,test_text):
            return("option {}".format(test_text))
    
        option_1.set_name('foo')
    

    问题3

    这个 __call__ 示例中的方法不返回函数。它正在返回 结果 function_ptr 召唤。但是如果您使用 async def yield 将函数转换为返回生成器对象的函数。