【发布时间】:2025-12-10 01:00:02
【问题描述】:
我正在编写一个 GUI 库,我想让程序员提供关于他们的程序的元信息,我可以使用这些元信息来微调 GUI。我打算为此使用函数装饰器,例如:
class App:
@Useraction(description='close the program', hotkey='ctrl+q')
def quit(self):
sys.exit()
问题是这些信息需要绑定到相应的类。例如,如果程序是一个图像编辑器,它可能有一个Image 类,它提供了更多的用户操作:
class Image:
@Useraction(description='invert the colors')
def invert_colors(self):
...
但是,由于在 python 3 中取消了未绑定方法的概念,似乎没有办法找到函数的定义类。 (我找到了this old answer,但这在装饰器中不起作用。)
那么,既然装饰器看起来不起作用,那么最好的方法是什么?我想避免使用类似的代码
class App:
def quit(self):
sys.exit()
Useraction(App.quit, description='close the program', hotkey='ctrl+q')
如果可能的话。
为了完整起见,@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
【问题讨论】:
-
您可以另外使用类装饰器或元类来检查方法并将其元数据保存在类中。
-
getattr(inspect.getmodule(f), f.__qualname__.rsplit('.', 1)[0])可能很老套,但可以省去编写元类的麻烦。字符串f.__qualname__.rsplit('.', 1)[0]可能已经足以作为您的defaultdict的键 -
f.__qualname__.split('.')[0]可以工作,并为您提供类名,这可能足以作为 dict 键。 -
@schwobaseggl 这可行。以这种方式编写代码感觉不太好,但我想它不会在大多数实际场景中造成问题,而且它比元类更容易/更好使用。
-
我刚刚意识到如果我只使用类的名称,会导致继承问题。类不会从其父类继承任何元数据。也许元类毕竟是要走的路。
标签: python python-3.x decorator