Ara*_*Fey 5 python decorator python-3.x
我正在编写一个 GUI 库,我想让程序员提供有关他们程序的元信息,我可以用它来微调 GUI。我打算为此目的使用函数装饰器,例如这样:
class App:
@Useraction(description='close the program', hotkey='ctrl+q')
def quit(self):
sys.exit()
Run Code Online (Sandbox Code Playgroud)
问题是这些信息需要绑定到相应的类。例如,如果该程序是图像编辑器,它可能有一个Image提供更多用户操作的类:
class Image:
@Useraction(description='invert the colors')
def invert_colors(self):
...
Run Code Online (Sandbox Code Playgroud)
然而,由于未绑定方法的概念已在 python 3 中删除,因此似乎没有办法找到函数的定义类。(我找到了这个旧答案,但这在装饰器中不起作用。)
那么,既然装饰器看起来不起作用,那么最好的方法是什么?我想避免使用类似的代码
class App:
def quit(self):
sys.exit()
Useraction(App.quit, description='close the program', hotkey='ctrl+q')
Run Code Online (Sandbox Code Playgroud)
如果可能的话。
为了完整起见,@Useraction装饰器看起来有点像这样:
class_metadata= defaultdict(dict)
def Useraction(**meta):
def wrap(f):
cls= get_defining_class(f)
class_metadata[cls][f]= meta
return f
return wrap
Run Code Online (Sandbox Code Playgroud)
您正在使用装饰器将元数据添加到方法中。没事儿。可以这样完成:
def user_action(description):
def decorate(func):
func.user_action = {'description': description}
return func
return decorate
Run Code Online (Sandbox Code Playgroud)
现在,您想要收集该数据并将其存储在 form 的全局字典中class_metadata[cls][f]= meta。为此,您需要找到所有修饰方法及其类。
最简单的方法可能是使用元类。在元类中,您可以定义创建类时会发生什么。在这种情况下,遍历类的所有方法,找到修饰的方法并将它们存储在字典中:
class UserActionMeta(type):
user_action_meta_data = collections.defaultdict(dict)
def __new__(cls, name, bases, attrs):
rtn = type.__new__(cls, name, bases, attrs)
for attr in attrs.values():
if hasattr(attr, 'user_action'):
UserActionMeta.user_action_meta_data[rtn][attr] = attr.user_action
return rtn
Run Code Online (Sandbox Code Playgroud)
我将全局字典放在user_action_meta_data元类中只是因为它感觉合乎逻辑。它可以在任何地方。
现在,只需在任何类中使用它即可:
class X(metaclass=UserActionMeta):
@user_action('Exit the application')
def exit(self):
pass
Run Code Online (Sandbox Code Playgroud)
静态UserActionMeta.user_action_meta_data现在包含您想要的数据:
defaultdict(<class 'dict'>, {<class '__main__.X'>: {<function exit at 0x00000000029F36C8>: {'description': 'Exit the application'}}})
Run Code Online (Sandbox Code Playgroud)