Python:使用装饰器来改变方法参数是件坏事吗?

时间:2016-03-09 03:17:58

标签: python

我实现了一个装饰器来以这种方式改变类方法的参数:

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()

some_decorator的主要目的是在SomeClass的每个项目上自动调用方法,然后进行一些清理。由于可能需要在项目上调用许多方法,因此我不想重复编写for循环和clean_items代码。

如果没有装饰者,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_status的参数与update_status声明的参数不同,item被遗漏,因为{{1}自动传递}}。我想知道这是不是一件坏事,因为当其他程序员看到它时可能会引起混淆。

如果这确实是一个非常糟糕的模式,是否有任何其他模式可以为我做同样的事情而不会引起混淆?

2 个答案:

答案 0 :(得分:2)

是的,我认为在这种情况下,更明确的更好。为什么不关闭装饰器并在方法本身中使用for-loops:

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

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

答案 1 :(得分:2)

我认为即使是无聊的模块级功能也是一个很好的选择。看起来 你的类实例的这些操作似乎没有任何合理的理由来属于"属于"作为一个类方法的类。

def update_status(some_item_haver, new_status):
    for item in some_item_haver.items:
        item.update_status(new_status)

现在,它可以与许多不同的类一起使用,即使是那些使用装饰器进行修改的方法也是一种不明智的方法,就像其他人写的库中的第三方类一样。

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')