[英]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
您將方法包裝器實現為自定義可調用對象,而不是常規函數對象。 這意味着您必須實現__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'
參見描述符方法指南
可調用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')
您的示例中的__call__
方法沒有返回函數。 它返回function_ptr
調用的結果 。 但這將是一個協程對象,如果您使用async def
定義選項,那么如果您在函數體內使用async / await語法,則無論如何都必須這樣做。 這類似於yield
將函數轉換為返回生成器對象的函數的方式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.