2010-07-07 89 views
1

是否可以擴展一個應用了裝飾器的類?例如:在Python中擴展裝飾類

@someDecorator 
Class foo(object): 
    ... 
    ... 

Class bar(foo): 
    ... 
    ... 

理想情況下bar不會受裝飾者的影響,但首先我想知道這是否可能。目前,我得到一個非運行時錯誤:

「類型錯誤:錯誤調用元類基地 ()函數的參數1必須是代碼的時候,沒有str的 」

有什麼建議?

回答

0

正如馬特所說的,你的裝飾器不工作。每當你得到你的裝飾正常工作(通過複製做一些測試,甚至imediate測試,並粘貼到一個控制檯):

什麼的(有效)裝飾返回類「富」 - 你不能訪問如果使用裝飾器語法,裝飾器在應用之前是什麼。

但是,Python中的裝飾器是一種合成糖,它可以用裝飾器處理該函數或類來返回以下聲明的函數或類。因此,這些是等價的:

@someDecorator 
class foo(object): 
    pass 

class foo(object): 
    pass 
foo = someDecorator(foo) 

因此,你可以簡單地通過執行實現應用裝飾前擴展一個類的效果:

class foo(object): 
    pass 
class bar(foo): 
    pass 

foo = someDecorator(foo) 
+0

很好的解釋,謝謝。我想我現在理解裝飾器有點更好了。 – Graham 2010-07-08 15:43:43

2

是的,只要@someDecorator實際上正在返回一個類是可能的。類裝飾器將類作爲它的參數,並且應該幾乎總是返回一個類,除非你正在做非常不尋常的事情。

foo,在這種情況下,將被綁定到任何@someDecorator返回。

這是裝修工會返回其他東西? A str

1

對於任何希望對於所選答案的替代方案,我發現最適合我的方式是在類裝飾器中裝飾__init__。例如:

def some_decorator(cls): 
    def decorate_init(func): 
     def decorated(*args, **kwargs): 
      func(*args, **kwargs) # Run __init__ 
      instance = args[0] 
      # Do whatever you need with the newly constructed instance 
     return decorated 
    cls.__init__ = decorated_init(cls.__init__) 
    return cls