2012-09-18 48 views
4

我剛剛遇到Python裝飾器。出於興趣,您可以將自己的裝飾器以某種方式應用於內置對象方法嗎?說我想申請這個:是否可以將我自己的裝飾器應用於Python中的內置方法?

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

要這樣:

some_string.split('\n') 

,以去除空字符串。可能嗎?甚至是一個好主意?

+1

你希望split()方法總是在應用程序的每次調用中刪除空字符串? –

+0

好點。這可能是一個不好的例子,但我仍然想知道它是否可能... – muskrat

回答

6

這有可能在一定意義;這取決於你的意思。這樣的裝飾語法...

@dec 
def foo(): 
    pass 

真的只是糖這樣的:

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

所以沒有什麼使用上的全局命名空間的預定義功能的裝飾阻止你。

func = dec(func) 

但是內置類的方法,生活在類的命名空間,該命名空間不能直接修改,如chepner已經指出。這是件好事,因爲它可以確保類型爲str的對象的行爲符合預期!但是,你可以海峽和裝飾方法那樣:

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

在這種的情況下,特別是的例子,我更喜歡一個明確的過濾器。但我可以想象,例如,一個內置類的子類,它可以執行一些memoization或類似的事情。

+0

也可以通過替換內置的'__builtins __。str = WeirdString'來使你的子類替換現有的'str'。但是,這並不影響''''或''「'構造函數,只有在你真正理解你在做什麼的情況下才應該這樣做。 –

1

當然是了。只寫

remove_empty(lambda: some_string.split('\n'))() 
+0

這只是返回一個新函數,你需要再次調用過濾'some_string'。它不會將裝飾器應用於'str.split'。 – chepner

+1

@chepner它將一個裝飾器應用於一個函數,並調用結果。 – ecatmur

+0

抱歉,括號失明。我最終沒有看到多餘的一對來調用函數。 – chepner

3

恐怕答案是否定的。在定義函數時應用裝飾器,並且預定義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' 
相關問題