5

Pythonデコレータに出くわしました。興味深いことに、組み込みのオブジェクト メソッドに独自のデコレータを適用できますか? これを適用したいとします:

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

これに:

some_string.split('\n')

空の文字列を削除するため。出来ますか?それとも良いアイデアですか?

4

3 に答える 3

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']

この特定の例の場合、明示的なフィルターを使用したいと思います。しかし、たとえば、メモ化などを行う組み込みクラスのサブクラスを想像できます。

于 2012-09-18T12:14:47.060 に答える
5

答えはノーだと思います。デコレータは、関数が定義されたときに適用され、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'
于 2012-09-18T11:52:42.107 に答える
1

もちろん。書くだけ

remove_empty(lambda: some_string.split('\n'))()
于 2012-09-18T11:51:35.820 に答える