我刚刚遇到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'))()