我刚刚接触到Python装饰器。出于兴趣,你能否将自己的装饰器应用于内置对象方法?比如说,如果我想要应用这个装饰器:
def remove_empty(fn):
def filtered():
return filter(lambda x: x != '', fn())
return filtered
到这个:
some_string.split('\n')
如何去除空字符串?这是可能的吗?或者说这是一个好主意吗?
我刚刚接触到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
:__builtins__.str = WeirdString
。但这不会影响 ''
或 ""
构造函数,只有在你真正理解自己在做什么时才应该这样做。 - Matthew Trevor<filter at 0x4d3b9b0>
而不是['This decorator is unnecessary']
。 - Adrian Keisterfilter
返回的值是一个迭代器而不是列表。因此,调用filter
需要包装在list
的调用中。我会添加一条注释--感谢您的评论! - senderlelist[filter(...
,我会得到 TypeError: 'type' object is not subscriptable 的错误提示。 - Adrian Keisterlist(filter(...
。 - senderlestr.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'))()
some_string
。它不会将装饰器应用于 str.split
。 - chepner