有可能将我自己的decorator应用于Python中的内置方法吗



我刚刚遇到Python装饰器。出于兴趣,您能以某种方式将自己的decorator应用于内置对象方法吗?假设我想应用这个:

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

对此:

some_string.split('n')

以便移除空字符串。有可能吗?甚至是个好主意?

这在某种意义上是可能的;这取决于你的确切意思。像这样的装饰器语法。。。

@dec
def foo():
pass

这真的只是糖:

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

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

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 unnecessarynnn'.split('n')
['This decorator is unnecessary', '', '', '']
>>> WeirdString('This decorator is unnecessarynnn').split('n')
['This decorator is unnecessary']

或者更直接地(因此更符合装饰者使用的精神):

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

在这个特定的例子中,我更喜欢显式过滤器。但我可以想象,例如,一个内置类的子类可以做一些记忆或类似的事情。

恐怕答案是否定的。在定义函数时会应用decorator,并且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'

当然是。只需编写

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

最新更新