Python:使用decorator更改方法参数是件坏事吗?

Python:使用decorator更改方法参数是件坏事吗?,python,Python,我实现了一个decorator,以这种方式更改类方法的参数: def some_decorator(class_method): def wrapper(self, *args, **kargs): if self._current_view = self.WEAPON: items = self._weapons elif self._current_view = self.OTHER: items = s

我实现了一个decorator,以这种方式更改类方法的参数:

def some_decorator(class_method):
    def wrapper(self, *args, **kargs):
        if self._current_view = self.WEAPON:
            items = self._weapons
        elif self._current_view = self.OTHER:
            items = self._others
        for item_id, item in items.iteritems():
            class_method(self, item, *args, **kargs)
        items_to_remove = []
        for item_id, each_item in items.iteritems:
            if each_item.out_dated():
                item_to_remove.append(item_id)
        for item_id in items_to_remove:
            del items[item_id]
    return wrapper

class SomeClass(object):
    @some_decorator
    def update_status(self, item, status):
        item.update_status(status)

    @some_decorator
    def refresh(self, item):
        item.refresh()
somedecorator
的主要目的是自动调用
SomeClass
的每个项上的方法,然后进行一些清理。因为可能有很多方法需要调用这些项,所以我不想重复编写for循环和
clean_items
code

如果没有decorator,
SomeClass
将类似于:

class SomeClass(object):
    def update_status(self, status):
        if self._current_view = self.WEAPON:
            items = self._weapons
        elif self._current_view = self.OTHER:
            items = self._others
        for item_id, item in items.iteritems():
            item.update_status(status)
        items_to_remove = []
        for item_id, each_item in items.iteritems:
            if each_item.out_dated():
                item_to_remove.append(item_id)
        for item_id in items_to_remove:
            del items[item_id]

    @some_decorator
    def refresh(self):
        if self._current_view = self.WEAPON:
            items = self._weapons
        elif self._current_view = self.OTHER:
            items = self._others
        for item_id, item in items.iteritems():
            item.refresh()
        items_to_remove = []
        for item_id, each_item in items.iteritems:
            if each_item.out_dated():
                item_to_remove.append(item_id)
        for item_id in items_to_remove:
            del items[item_id]
当我实际使用这些方法时,我会:

a = SomeClass()
a.update_status(1)
a.refresh()
问题是,我传递给
update\u status
的参数与
update\u status
声明的参数不同,
丢失,因为它是由
某个装饰程序自动传递的。我想知道这是否是一件坏事,因为当其他程序员看到它时,它可能会引起混乱


如果这确实是一个非常糟糕的模式,有没有其他模式可以在不引起混乱的情况下为我做同样的事情?

是的,我认为在这种情况下,越明确越好。为什么不关闭decorator,只用于方法本身中的循环:

def update_status(self, status):
    for item in self.items:
        item.update_status(status)

def refresh(self):
    for item in self.items:
        item.refresh()

我认为即使是一个无聊的模块级函数在这里也是一个很好的选择。这些发生在类实例上的操作似乎根本没有任何理由作为类方法“属于”类

def update_status(some_item_haver, new_status):
    for item in some_item_haver.items:
        item.update_status(new_status)
现在,它可以与许多不同的类一起使用,即使是那些使用decorator修改其方法会带来不明智的痛苦的类,比如其他人编写的库中的第三方类

a = SomeClass()
b = SomeChildOfA()
c = SomeThirdPartyThingAlsoWithItems()

update_status(a, "beep")
update_status(b, "bop")
update_status(c, "Vote for Bernie Sanders!")
更新后编辑

class SomeClass(object):
    # __init__ and other stuff
    #...

    def helper(self, func, *args, **kwargs):
        if self._current_view == self.WEAPON:
            items = self._weapons
        elif self._current_view == self.OTHER:
            items = self._others


        # The abstract part
        for item_id, item in items.iteritems():
            getattr(item, func)(*args, **kwargs)


        items_to_remove = []
        for item_id, each_item in items.iteritems:
            if each_item.out_dated():
                item_to_remove.append(item_id)
        for item_id in items_to_remove:
            del items[item_id]


    def update_status(self, status):
        self.helper('update_status', status)

    def refresh(self):
        self.helper('refresh')

我使用decorator的原因是,对于不同的方法,如
update\u status
refresh
有太多类似for循环的代码行,我不想重复手工编写(这很烦人而且容易出错。@在这种情况下,编写另一个只执行循环部分的helper函数,
update_status
的主体将使用一些额外的参数调用循环函数。另外,为什么会重复很多行?重复for语句的单行应该没有问题,如果逻辑循环是必要的,对于每个不同的函数都是不同的,它不是重复的。如果你能更新问题中的示例,我们可能能够帮助找出重复的部分。好的,根据问题的新编辑版本,我倾向于同意这种装饰。仍然认为一些重构可能会e必需。我想说的是,
\u item\u list
的容器类/mixin可能比仅仅使用列表更有用。然后让该类接受一个函数,然后它像装饰器一样执行。是的,它是附加代码,具有与装饰器相同的功能,但在将来更干净、更易于维护。只是我的2 cen一个很好的问题。希望不要太宽泛。(顺便说一句,编辑有一些打字错误/语法错误。)在较长版本的
refresh
中,变量
status
从何而来?这看起来仍然很容易将公共部分分解为第三个helper函数,然后
update\u status
refresh
中的每一个都会简单地调用该helper函数,可能会使用不同的参数来实现不同的行为。装饰方法对我来说仍然是个坏主意。@aneroid谢谢,你能发布一个示例容器作为答案吗?是的,正在研究;-)尝试在子分类
列表
还是。请参阅我的编辑,以获得一种比decorator简单得多的抽象方法。谢谢。这与我第一次编写的内容非常接近。然后我使用decorator来避免使用
getattr(item,func)(*args,**kargs)
。但是装饰程序似乎会引起更多的混乱,所以我可能会回到
getattr
函数调用。这几乎就是我在OP编辑之后要做的,但我没有想到要制作这样一个简化的帮助器。很好!我正在计划一个基于
列表的混入来管理项目,而不仅仅是在类中并运行对于
self
,将
SomeClass
的实例单独传递给它,而不是在
\uuuu init\uuuu
中。