python - 装饰器是否可以返回一个与包装函数具有相同参数的函数?

标签 python decorator

因此,为了方便起见,我正在编写一个简单的堆数据结构,并意识到要正确执行此操作,我需要检查许多参数是否可哈希,以便 heapq 操作正常工作。

import heapq


def hashable(func):
    def hidden(self, item):
        try:
            hash(item)
            func(self, item)
        except TypeError as e:
            raise e
    hidden.__doc__ = func.__doc__
    return hidden


class heap(object):
    def __init__(self, heap=[]):
        self.heap = heap
        heapq.heapify(heap)

    def pop(self):
        '''
        Pop and return the smallest item from the heap, maintaining the heap
        invariant. If the heap is empty, IndexError is raised.
        '''
        return heapq.heappop(self.heap)

    @hashable
    def push(self, item):
        '''
        Push the value item onto the heap, maintaining the heap invariant.
        '''
        return heapq.heappush(self.heap, item)

    @hashable
    def pushpop(self, item):
        '''
        Push item on the heap, then pop and return the smallest item from
        the heap.

        The combined actions runs more efficiently than heappush()
        followed by a separate called to heappop().'''
        heapq.heappushpop(self.heap, item)

    @hashable
    def poppush(self, item):
        '''
        Pop and return the smallest item from the heap, then push item on
        the heap.

        The combined actions runs more efficiently than heappop()
        followed by a separate called to heappush().'''
        heapq.heapreplace(self.heap, item)

    def __setitem__(self, i, y):
        self.heap[self.heap.index(i)] = y
        heapq.heapify(self.heap)

    def __len__(self):
        return len(self.heap)

    def __iter__(self):
        while self.heap:
            yield self.pop()

我遇到的问题是 setitem。虽然 setitem 还要求“y”是可散列的,但如果我用可散列来装饰它,它将只能接受一个参数。

显而易见的解决方案只是更改 hashable 的隐藏函数以接受 'self' 和 '*args",但我对使用这样的解决方案犹豫不决,因为它不漂亮而且只会使代码复杂化。

那么我的问题是,是否可以重写代码,使 hidden 采用传递给装饰器的函数的参数?

最佳答案

为什么要使 hashable 成为装饰器?为什么不把它做成一个你可以调用的函数,它会正常引发异常,然后在函数体中调用它,将你想要检查的东西传递给它?

其实从你写装饰器的方式来看,hash()不就是这样吗?为什么不,而不是这个:

@hashable
def push(self, item):
    '''
    Push the value item onto the heap, maintaining the heap invariant.
    '''
    return heapq.heappush(self.heap, item)

就写这个?

def push(self, item):
    '''
    Push the value item onto the heap, maintaining the heap invariant.
    '''
    hash(item)
    return heapq.heappush(self.heap, item)

如果你那样做,那么它会解决你的 __setitem__ 问题:

def __setitem__(self, i, y):
    hash(i), hash(y)
    self.heap[self.heap.index(i)] = y
    heapq.heapify(self.heap)

也就是说,对于你关于“返回具有相同参数的函数”的问题 - 正是 *args**kwargs 语法是为以下目的而设计的,所以我不确定您为什么认为它“不漂亮”或“使代码复杂化”。

关于python - 装饰器是否可以返回一个与包装函数具有相同参数的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7212083/

相关文章:

c# - 无需装饰器的反序列化

python - 如何在没有固定宽度字段组织的情况下对输入进行排序?

Python Raspberry pi - 如果路径不存在,则跳过循环

python - 将图标移动到 QCheckBox 中文本的右侧

python - 一种在 settings.py 中设置 Django SITEURL 常量的方法

python - Python 装饰器的参数

python - Django如何管理只有小时和分钟的格式时间

javascript - 测试 typescript 装饰器

python - 解释Python装饰器是如何工作的

python - 将关键字参数传递给类方法装饰器