python - 如何编写与使用它的类具有相同导入的装饰器?

标签 python class import decorator

如何在 Python 中编写一个装饰器,它具有一些导入 from Foo import Foo ,当我想将它用于也具有此导入的类的方法时,这是必需的?

将导入放入两个单独的文件中会导致错误,告诉我无法从 Foo 导入 Foo。

如果不可能的话: 如果装饰器不打算在其他地方使用,将装饰器放入与类相同的文件中,这样我只需编写一次导入,并且它不会与任何其他导入冲突,这是一个好主意吗? ?

在我的真实示例中,我想编写一个装饰器,它只是更改一个标志,该标志指示列表是否已更改。该类中修改列表的每个方法都将使用该装饰器进行装饰。

编辑#1:

更改代码结构后,我现在只有两个参与源代码文件。具体如下:

# -*- coding: utf-8 -*-
from AppSettings import AppSettings
from FileManager import FileManager
from decorators.changesvocables import changesvocables
from exceptions.DuplicateVocableException import DuplicateVocableException
from exceptions.UnknownVocableException import UnknownVocableException

__author__ = 'xiaolong'


class VocableManager:

    vocables = []
    search_result = []
    vocables_changed = False

    test_counter = 0
    test_call_counter = 0

    def __init__(self):
        pass

    @classmethod
    @changesvocables
    def remove_vocable(cls, vocable):
        VocableManager.test_call_counter += 1
        if vocable in VocableManager.vocables:
            VocableManager.test_counter += 1
            VocableManager.vocables.remove(vocable)
            # del vocable
        else:
            print(vocable)
            raise UnknownVocableException('Vocable not found.')
        # VocableManager.vocables_changed = True

    @classmethod
    @changesvocables
    def remove_vocable_by_index(cls, index):
        del VocableManager.vocables[index]
        # VocableManager.vocables_changed = True

    @classmethod
    @changesvocables
    def add_vocable(cls, vocable):
        if vocable not in VocableManager.vocables:
            VocableManager.vocables.append(vocable)
        else:
            raise DuplicateVocableException('The vocable already exists.')
        # VocableManager.vocables_changed = True

之后类(class)仍然继续,但没有其他带有 changesvocables 装饰的方法。如果需要,我可以添加整个类(class)。

和装饰器:

# -*- coding: utf-8 -*-
from functools import wraps
from VocableManager import VocableManager as VocMan

__author__ = 'xiaolong'


def changesvocables(function):
    @wraps(function)
    def wrapper(*args, **kw):
        result = function(*args, **kw)
        VocMan.vocables_changed = True
        return result
    return wrapper

当我尝试运行应用程序时,这会导致以下错误:

** (__main__.py:16991): WARNING **: Couldn't connect to accessibility bus: Failed to connect to socket /tmp/dbus-sQwlsgyRi2: Connection refused
Traceback (most recent call last):
  File "/home/xiaolong/development/pycharm-workspace/gtkplus-tool/gtkplustool/__main__.py", line 1, in <module>
    from Application import Application
  File "/home/xiaolong/development/pycharm-workspace/gtkplus-tool/gtkplustool/Application.py", line 8, in <module>
    from VocableManager import VocableManager
  File "/home/xiaolong/development/pycharm-workspace/gtkplus-tool/gtkplustool/VocableManager.py", line 4, in <module>
    from decorators.changesvocables import changesvocables
  File "/home/xiaolong/development/pycharm-workspace/gtkplus-tool/gtkplustool/decorators/changesvocables.py", line 3, in <module>
    from VocableManager import VocableManager as VocMan
ImportError: cannot import name 'VocableManager'

编辑#3:

这是一个 MCVE:

main.py:

# -*- coding: utf-8 -*-
from mcve.ListManager import ListManager

__author__ = 'xiaolong'

if __name__ == '__main__':
    list_manager = ListManager()
    list_manager.add_item('item1')

装饰器:

# -*- coding: utf-8 -*-
from functools import wraps
from mcve.ListManager import ListManager as ListMan

__author__ = 'xiaolong'


def changesitems(function):
    @wraps(function)
    def wrapper(*args, **kw):
        result = function(*args, **kw)
        ListMan.vocables_changed = True
        return result
    return wrapper

列表管理器:

# -*- coding: utf-8 -*-
from mcve.changesitems import changesitems


class ListManager:

    list_of_items = []

    def __init__(self):
        pass

    @changesitems
    def add_item(self, item):
        if item not in ListManager.list_of_items:
            ListManager.add_item(item)

与之前相同的错误:

Traceback (most recent call last):
  File "/home/xiaolong/development/pycharm-workspace/MCVE/mcve/main.py", line 2, in <module>
    from mcve.ListManager import ListManager
  File "/home/xiaolong/development/pycharm-workspace/MCVE/mcve/ListManager.py", line 2, in <module>
    from mcve.changesitems import changesitems
  File "/home/xiaolong/development/pycharm-workspace/MCVE/mcve/changesitems.py", line 3, in <module>
    from mcve.ListManager import ListManager as ListMan
ImportError: cannot import name 'ListManager'

Process finished with exit code 1

最佳答案

尝试:

from Foo import Foo as foo

现在您将可以访问包(如 Foo)和装饰器(如 foo)。

关于python - 如何编写与使用它的类具有相同导入的装饰器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32673239/

相关文章:

python - 将具有连续 block 项目但不连续 block 的列表拆分为子列表

javascript - 在 JavaScript 中使用哪种方式来定义类

c++ - 如何在类函数中正确初始化指针?

php - 我应该使用静态方法和属性来检测语言和翻译文本吗?

javascript - RequireJS:找不到模块 'domReady'

python - Python 用于导入模块的顺序是什么?

python - 如何杀死由同一类中的不同函数启动的子进程

python - 当鼠标悬停在窗口上时在 Tkinter 中显示按钮

python - 获取列表中列表元素的索引

mysql - 如何在不更改其中数据的情况下将表的架构从一个数据库导入到另一个数据库中的现有表?