2014-09-20 150 views
4

有沒有辦法「註銷」一個通用的註冊函數?取消註冊singledispatch?

例如:

from functools import singledispatch 

@singledispatch 
def foo(x): 
    return 'default function' 

foo.register(int, lambda x: 'function for int') 

# later I would like to revert this. 

foo.unregister(int) # does not exist - this is the functionality I am after 
+0

這也許值得指出的是,儘管馬亭的答案證明你*可以*,實際上,做到這一點,你可能*不應該*:singledispatch的設計者作出了[有意識的決定](http://permalink.gmane.org/gmane.comp.python.devel/ 139709)通過暴露一個['mappingproxy'](https://docs.python.org/3/library/type s.html#types.MappingProxyType)而不是常規字典。 – 2014-09-20 18:30:26

+0

@ZeroPiraeus我注意到,註銷一個函數正是他們試圖阻止的東西。它看起來像註冊函數的反射(改變通用函數的函數)。 – lgautier 2014-09-20 20:30:44

回答

4

singledispatch意味着是追加僅;你不能真正註銷任何東西。

但是與Python的所有東西一樣,的執行可能會被強制取消註冊。下面的函數會unregister()方法添加到singledispatch功能:

def add_unregister(func): 
    # build a dictionary mapping names to closure cells 
    closure = dict(zip(func.register.__code__.co_freevars, 
         func.register.__closure__)) 
    registry = closure['registry'].cell_contents 
    dispatch_cache = closure['dispatch_cache'].cell_contents 
    def unregister(cls): 
     del registry[cls] 
     dispatch_cache.clear() 
    func.unregister = unregister 
    return func 

這伸進singledispatch.register()功能關閉訪問實際registry字典,所以我們可以刪除已註冊現有的類。我也很清楚了dispatch_cache弱引用字典,以防止其在加強

您可以使用此作爲裝飾。

@add_unregister 
@singledispatch 
def foo(x): 
    return 'default function' 

演示:

>>> @add_unregister 
... @singledispatch 
... def foo(x): 
...  return 'default function' 
... 
>>> foo.register(int, lambda x: 'function for int') 
<function <lambda> at 0x10bed6400> 
>>> foo.registry 
mappingproxy({<class 'object'>: <function foo at 0x10bed6510>, <class 'int'>: <function <lambda> at 0x10bed6400>}) 
>>> foo(1) 
'function for int' 
>>> foo.unregister(int) 
>>> foo.registry 
mappingproxy({<class 'object'>: <function foo at 0x10bed6510>}) 
>>> foo(1) 
'default function' 
+0

謝謝。我很驚訝這個功能不是singledispatch的一部分。 – lgautier 2014-09-20 18:10:32

+1

@ lgautier:這種感知的用例就是你構造這個*一次*,而不是像你一樣改變調度規則。 – 2014-09-20 18:20:22

+0

@ martjin-pieters:由於Python是動態的,因此似乎沒有必要限制不允許它。從技術角度而言,調度規則隨着人們的發展而變化(因爲Python代碼被評估,並且泛型的新功能被註冊)。無論如何,這更可能是關於python-ideas或可能是python-dev的討論。再次感謝您的回答。 – lgautier 2014-09-20 20:20:58