2011-11-30 113 views
21

「Python裝飾器」和「裝飾器模式」有什麼區別?Python裝飾器和裝飾器模式有什麼區別?

什麼時候應該使用Python裝飾器,何時應該使用裝飾器模式?

我正在尋找Python裝飾器和裝飾模式實現相同的例子嗎?


@AcceptedAnswer
我知道Jakob Bowyer's answer是有效的。然而,Strikar的回答讓我明白了原因。


在Srikar的回答和研究給出資源後,我寫了這個例子,所以我可以看到和理解Python裝飾器和裝飾器模式。

我必須不同意與Strikar的「Python的裝飾都沒有裝飾圖案的實現」。在我學到的東西後,我堅信Python裝飾器是Decorator模式的實現。只是沒有經典的方式。

此外,我需要補充的是儘管Strikar說:「Python的裝飾在定義時函數和方法添加功能」 你可以很容易地使用Pytohon裝飾在運行時

但是,我仍然將Stiker的答案標記爲已接受,因爲它幫助我理解了裝飾器模式的ImplementationPython

""" 
Testing Python decorators against Decorator Pattern 
""" 
def function(string): 
    return string 

def decorator(wrapped): 
    def wrap(string): 
     # assume that this is something useful 
     return wrapped(string.upper()) 
    return wrap 

def method_decorator(wrapped): 
    def wrap(instance, string): 
     # assume that this is something useful 
     return wrapped(instance, string.upper()) 
    return wrap 

@decorator 
def decorated_function(string): 
    print('! '.join(string.split(' '))) 

class Class(object): 
    def __init__(self): 
     pass 
    def something_useful(self, string): 
     return string 

class Decorator(object): 
    def __init__(self, wrapped): 
     self.wrapped = wrapped 
    def something_useful(self, string): 
     string = '! '.join(string.split(' ')) 
     return self.wrapped().something_useful(string) 

    @method_decorator 
    def decorated_and_useful(self,string): 
     return self.something_useful(string) 


if __name__ == '__main__': 
    string = 'Lorem ipsum dolor sit amet.' 
    print(function(string))     # plain functioon 
    print(decorator(function)(string))  # Python decorator at run time 
    print(decorated_function(string))  # Python decorator at definition time 
    a = Class() 
    print(a.something_useful(string))  # plain method 
    b = Decorator(Class) 
    print(b.something_useful(string))  # Decorator Pattern 
    print(b.decorated_and_useful(string)) # Python decorator decorated Decorator Pattern 
+1

@Srikar是正確的。 [Here](http://stackoverflow.com/q/3118929/146792)的另一個SO問題,你可能會覺得有趣! – mac

+1

@Srikar,我不能接受Snswer,它不能解決Question中描述的問題,對不起,但是我的問題中提出的大多數解決方案都不起作用。 – seler

+0

@seler夠公平的。 –

回答

24

修飾器模式 - 在面向對象編程中,修飾器模式是一種設計模式,允許將行爲動態添加到現有對象。裝飾器模式可以用來在運行時擴展(修飾)某個對象的功能,而不依賴於同一類的其他實例,前提是在設計時進行一些基礎工作。

Python中的裝飾器 - 儘管有這個名稱,Python裝飾器並不是裝飾器模式的實現。裝飾器模式是靜態類型的面向對象編程語言中使用的設計模式,允許在運行時將功能添加到對象; Python裝飾器在定義時爲函數和方法添加功能,因此是比裝飾器模式類更高級別的構造。裝飾器模式本身在Python中是可以實現的,因爲語言是鴨子類型的,所以通常不會這樣認爲。所以在Python中,裝飾器是用於修改函數,方法或類定義的可調用Python對象。

我希望我能明確區別。以防萬一您完全不瞭解,請通過這些鏈接。你會出來比更清晰,在它的結束 -

How to make a chain of function decorators?

Implementing the decorator pattern in Python

What is the difference between using decorators and extending a sub class by inheritance?

Python Class Decorator

PyWiki - Python Decorators - A detailed discourse

Python Decorators Made Easy

source1 & source2

+0

你可能想看看編輯的問題。 – seler

0

python中的裝飾器是裝飾器設計中裝飾器的應用。它們與人們在談論語言實現以及設計和計算機科學概念的另一個方面是一回事。

+0

nope在這裏看到http://wiki.python.org/moin/DecoratorPattern – Freelancer

1

所不同的是這樣的:

(a)中的Python裝飾被綁定到現有的方法和改變方法的行爲。例如:

@modifyBehavior 
def original(myString): 
    print myString 

原件的行爲被覆蓋。您不能使用它來添加新功能。 (b)Decorator模式是關於多態性的。在上面的示例代碼中,Decorator.something_useful的行爲被覆蓋。原來的方法丟失了。這不是真正的裝飾模式。您應該期望增強或添加功能,而不是替換方法。您應該確保a.something_useful(string)返回與b.something_useful(string)相同的內容。實際上,在裝飾模式中,您通常會替換原始對象。這裏是我的意思:

class Class(object): 
    def __init__(self): 
     pass 
    def something_useful(self, string): 
     return string 

class Decorator(object): 
    def __init__(self, wrapped): 
     self._wrapped = wrapped 
    def withUnderscores(self, string): 
     return '_'.join(string.split(' ')) 
    def __getattr__(self, name): 
     return getattr(self._wrapped, name) 


if __name__ == '__main__': 
    string = 'Lorem ipsum dolor sit amet.' 
    obj = Class() 
    print('Original: ', obj.something_useful(string)) 
    #This has no underscore function. Use decorator to add. 
    obj = Decorator(obj) 
    print('Replaced spaces: ', obj.withUnderscores(string)) 
    print('Original still works: ', obj.something_useful(string)) 

你可以有幾個裝飾添加功能。這允許您只在需要時添加所需的內容。更多閱讀:GoF