2016-08-22 48 views
0

我知道我可以使用閉包和繼承來創建修飾類的修飾器。如何編寫適當的修飾器來改變類

def wrapper(cls, *args, **kwargs): 
    class Wrapped(cls): 
     """Modify your class here.""" 

    return Wrapped 

但是,如果我需要測試我的新類來知道他們是否繼承Wrapped與否,我無法訪問Wrapped本身做一個簡單的isinstanceissubclass測試。

另一方面,直接繼承不是一種選擇。我有大約10個不同的包裝可以需要添加到一個類。這對層次結構樹的方式負擔過重。

所以我需要一種方法從外部訪問封閉。或者另一種構建裝飾器的方法。

+0

「但是我需要測試我的新類,以確定它們是否繼承了「Wrapped」 - 我不確定_why_你需要測試它,爲什麼不測試它們的行爲是否正確?還要注意,裝飾類將會是' Wrapped',所以你可以測試'DecoratedClass .__ name__ =='Wrapped''如果你真的想要的話,但是這樣的感覺就像是一個黑客。 – mgilson

+1

你的包裝可以添加某種標記方法嗎?你可以測試 –

+0

如果我有很多'wrapped'對象,測試這個名稱不是一個選項。 您的意思只是'嘗試'來訪問修改發現任何錯誤? –

回答

2

這聽起來像你想檢查一個類是否被這個特定的裝飾器包裝。最有效的方法,這樣做可能只是一個字段添加到效果,即:

def wrapper(cls, *args, **kwargs): 
    class Wrapped(cls): 
     """Modify your class here.""" 

    Wrapped._is_wrapped_by_this_wrapper = True 
    return Wrapped 

然後你就可以檢查hasattr_is_wrapped_by_this_wrappergetattr

如果您有多個相互合作的包裝類,您可能會想出一個能夠更好地協同工作的解決方案,例如,也許一個set由所有已應用的包裝的名稱組成。

class WrapperBase: 
    pass 

def wrapper(cls, *args, **kwargs): 
    class Wrapped(cls, WrapperBase): 
     """Modify your class here.""" 

    return Wrapped 

現在對於isinstance(obj, WrapperBase)生成的類測試True的所有實例:

+0

有趣。它會解決我的問題。 –

1

你可以從兩個班,一個基類和cls繼承。

請注意,WrapperBase對查找MRO中的繼承方法沒有影響;它在任何層次結構中死亡最後(在Python 2上,不是從object繼承而來,它在MRO中最後死亡,在Python 3中它將位於object之間,並且在包裝類的MRO中包含在object之前

+0

但是後來我輸入了MRO衝突。當我需要繼承樹時會發生什麼。想到'__init__'。 –

+0

@AlexandreParent:'WrapperBase'沒有定義任何方法。當找到'__init__'和其他方法時''super()'''WrapperBase'不會有問題。無論如何它最後都會死去。 –