簡體   English   中英

將自我傳遞給python中的類裝飾器的問題

[英]Issues passing self to class decorator in python

我對裝飾器是陌生的,但理想情況下,我希望使用它們在類OptionClass中定義一堆類函數,每個函數均使用名稱和描述(如果需要)表示某個特定選項。 如果有必要,我根本不想修改類函數的操作,我只想使用裝飾器來定義名稱,描述以及是否需要它。

問題1:我構造了一個OptionClass(),我想稱其為option_1。 當我這樣做時,我收到TypeError,因為呼叫裝飾器未收到OptionClass的實例。 為什么是這樣? 當我調用option_1傳遞OptionClass()實例時,它可以工作。 如何調用option_1,而不必始終將實例作為自己傳遞。 收到時的錯誤是:

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:盡管這是一個示例,但我打算使用異步函數編寫一個選項類並對其進行修飾。 我是否需要將裝飾器調用設為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

您將方法包裝器實現為自定義可調用對象,而不是常規函數對象。 這意味着您必須實現__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'

參見描述符方法指南

問題2

可調用option_decorator實例取代了功能OptionClass字典。 這意味着對可調用實例進行OptionClass會影響使用該可調用對象的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定義選項,那么如果您在函數體內使用async / await語法,則無論如何都必須這樣做。 這類似於yield將函數轉換為返回生成器對象的函數的方式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM