如何使用与使用它的类相同的导入来编写装饰器?

时间:2015-09-19 21:04:58

标签: 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

之后,课程仍然继续,但没有其他方法changesvocables装饰。如果需要,我可以添加整个班级。

装饰者:

# -*- 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

ListManager:

# -*- 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

1 个答案:

答案 0 :(得分:2)

尝试:

from Foo import Foo as foo

现在,您可以Foo访问包,并以foo访问装饰器。