是否可以将我自己的装饰器应用于Python中的内置方法?

时间:2012-09-18 11:46:53

标签: python decorator

我刚遇到Python装饰器。只是出于兴趣,您可以以某种方式将自己的装饰器应用于内置对象方法吗?说我想申请这个:

def remove_empty(fn):
    def filtered():
        return filter(lambda x: x != '', fn())
    return filtered

对此:

some_string.split('\n')

为了删除空字符串。可能吗?或者甚至是个好主意?

3 个答案:

答案 0 :(得分:6)

从某种意义上说,这是可能的;这取决于你究竟是什么意思。像这样的装饰器语法...

@dec
def foo():
    pass

真的只是糖:

def foo():
    pass
foo = dec(foo)

因此没有什么可以阻止你在全局命名空间中的预定义函数上使用装饰器。

func = dec(func)

但是内置类的方法存在于该类的命名空间中,并且该命名空间不能直接修改,正如chepner已经指出的那样。这是一件好事,因为它确保str类型的对象将按预期运行!但是,你可以子类 str并以这种方式装饰方法。 (下面的内容适用于Python 2;在Python 3中,将filter的输出传递给列表。super也可能有所不同;我将来会发布Python 3更新。)

>>> def remove_empty(fn):
...     def filtered(*args, **kwargs):
...         return filter(lambda x: x != '', fn(*args, **kwargs))
...     return filtered
... 
>>> class WeirdString(str):
...     @remove_empty
...     def split(self, *args, **kwargs):
...         return super(WeirdString, self).split(*args, **kwargs)
... 
>>> 'This decorator is unnecessary\n\n\n'.split('\n')
['This decorator is unnecessary', '', '', '']
>>> WeirdString('This decorator is unnecessary\n\n\n').split('\n')
['This decorator is unnecessary']

或者更直接(以及装饰师使用的精神):

>>> class WeirdString2(str):
...     split = remove_empty(str.split)
... 
>>> WeirdString2('This decorator is unnecessary\n\n\n').split('\n')
['This decorator is unnecessary']

对于特定示例,我更喜欢显式过滤器。但我可以想象,例如,内置类的子类可以执行某些memoization或类似的事情。

答案 1 :(得分:4)

我担心答案是否定的。定义函数时应用装饰器,并预定义str.split。你可能会做一些明确的事情,比如

str.split = remove_empty(str.split)

但不允许这样做:

Traceback (most recent call last):
  File "tmp.py", line 8, in <module>
    str.split = remove_empty(str.split)
TypeError: can't set attributes of built-in/extension type 'str'

答案 2 :(得分:1)

当然是。只需写下

remove_empty(lambda: some_string.split('\n'))()