2017-02-20 65 views
4

我想知道是否可以在子類中使用描述符的裝飾器。如何在子類中使用描述符的裝飾器

class Descriptor(): 
    def __get__(self, instance_obj, objtype): 
     raise Exception('ouch.') 
    def decorate(self, f): 
     print('decorate', f) 
     return f 

class A(): 
    my_attr = Descriptor() 

class B(): 
    @my_attr.decorate 
    def foo(self): 
     print('hey, whatsup?') 

# --> NameError: name 'my_attr' is not defined 

這,當然,並不因爲my_attrB類定義中未定義的工作。

接着我嘗試:

class B(): 
    @A.my_attr.decorate 
    def foo(self): 
     print('hey, whatsup?') 

# --> Exception: ouch. 

但是,這種方法調用描述符__get__方法(其中instance_obj參數是None),因此該測試異常被觸發。要訪問一個裝飾可以檢查該instance_objNone的回報描述自己:

def __get__(self, instance_obj, objtype): 
    if instance_obj is None: 
     return self 
    raise Exception('avoid this') 
# --> decorate <function B.foo at 0x1021dd7b8> 

它的工作原理!但是這是否合理,或者在B的類定義中有沒有辦法使用裝飾器?

A.__dict__['my_attr'].decorate 

或清潔劑,使用vars()

回答

4

可以完全由從類的__dict__映射檢索原始對象繞過描述符協議

vars(A)['my_attr'].decorate 

然而,@修飾語法不允許訂閱(最後只給出屬性訪問和一次調用的簡單表達式),因此您必須首先提取字典:

_A_my_attr = vars(A)['my_attr'] 
@_A_my_attr.decorate 
def foo(self): 
    # ... 

但是,除非你必須捕獲結合的一類,它是更好地爲第一個參數後衛__get__None,因爲你發現了。這正是property對象或函數所做的。

+0

如果他想要一個全局的,我們不會把裝飾器放在一個類中 – JBernardo

相關問題