首页 > 解决方案 > 子函数的 Python 装饰器

问题描述

我正在设计一个名为的PyQt窗口FileOpenDialog。从 获取返回值后FileOpenDialogloadItem()将加载图像。我想记录这个事件并将其附加到日志中,这是一个 QListWidget。我想使用装饰器来实现这一点,以增强代码的可重用性和清洁度。

我创建了一个名为 的类装饰器logAction,它将QListWidget基于函数和 *args 附加一个字符串。

class logAction:
    def __init__(self, function):
        self.function=function
    def __call__(self, *args, **kwargs):
        if(function.__name__ == "promptOpen"):
            self.logOpen()

    def logOpen(*args, **kwargs):
        import re
        extensionPattern = re.compile(r"""
        ^(.+?)
        ([^\\]+)$
        """, re.VERBOSE)
        file = extensionPattern.search(args[0])

        self.log.addItem(f"Loaded {file}")


def promptOpen(self):
    self.openDialog = FileOpenDialog(self)

    @logAction
    def loadItem(path):
        pass

    loadItem(self.openDialog.filePath)

NameError:未定义名称“logAction”

错误在@logAction。我怎样才能让loadItem()被装饰logAction,而不是把类放在里面promptOpen()

标签: pythondecorator

解决方案


class test2:
    def __init__(self, func):
        self.func=func

    def __call__(self, *args, **kwargs):
        if(self.func.__name__ == "mama"):
            self.logOpen()
        return self.func(*args, **kwargs)

    def logOpen(self):
        print('well done')


def hi():

    @test2
    def mama():
        print('here')

    mama()

hi()

结果:这里做得很好

你写的if(function.__name__ == "loadItem"):没有 self asself.function.__name__并且函数的名称是错误的,它没有指向正确的函数名称

我只是试图以我的方式复制您的代码效果很好。

如果你添加你的代码会很好if(self.function.__name__ == "loadItem")

class logAction:
    def __init__(self, function):
        self.function=function
    def __call__(self, *args, **kwargs):
        if(self.function.__name__ == "loadItem"):
            self.logOpen()

    def logOpen(*args, **kwargs):
        import re
        extensionPattern = re.compile(r"""
        ^(.+?)
        ([^\\]+)$
        """, re.VERBOSE)
        file = extensionPattern.search(args[0])

        self.log.addItem(f"Loaded {file}")


def promptOpen(self):
    self.openDialog = FileOpenDialog(self)

    @logAction
    def loadItem(path):
        pass

    loadItem(self.openDialog.filePath)

推荐阅读