我刚刚遇到 Python 装饰器。只是出于兴趣,您能否以某种方式将自己的装饰器应用于内置对象方法?说我想应用这个:
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)
因此,没有什么可以阻止您在全局命名空间中的预定义函数上使用装饰器。
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']
在这个特定示例的情况下,我更喜欢显式过滤器。但我可以想象,例如,一个内置类的子类,它做一些记忆或类似的事情。
恐怕答案是否定的。定义函数时应用装饰器,并且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'))()