Python天天美味(34) – Decorators詳解

來源:互聯網
上載者:User
文章目錄
  • Decorators基礎
  • Decorators調用規律
  • Decorators典型應用 – singleton class

Python中的Decorators表面看起來很像C#的Attribute,其實不然,Python的Decorators和C#的Attribute完全是兩個東西。Python的Decorators讓我想到了設計模式中的裝飾者模式(Decorator Pattern)。

Decorator Pattern

Attach additional responsibilities to an object dynamically.
Decorators provide a flexible alternative to subclassing for extending functionnality.

Python中的通過Decorators對函數、方法或類進行裝飾,從而達到增加對象的職責,或控制對象調用的作用。而C#的Attribute僅僅是起到中繼資料標識作用,最終通過反射擷取這些特定資訊。

先來個簡單的樣本,先定義一個Coffee類,

class Coffee(object):
    def get_cost(self):
        return 1.0

coffee = Coffee()
print coffee.get_cost() # 1.0

這時,我想通過裝飾者模式計算Milk的價格,通常這樣實現:

class Milk(Coffee):
    def __init__(self, coffee):
        self.coffee = coffee
 
    def get_cost(self):
        return self.coffee.get_cost() + 0.5

coffee = Coffee()
coffee = Milk(coffee)
print coffee.get_cost() # 1.5

上面是經典的裝飾者模式的實現,Python中通過Decorators可以實現成這樣:

def milk_decorator(get_cost):
    def get_milk_cost(self):
        return get_cost(self) + 0.5
    return get_milk_cost

class Coffee(object):
    @milk_decorator
    def get_cost(self):
        return 1.0

coffee = Coffee()
print coffee.get_cost() #1.5

假設一下,如果有更多的,比如:Whip, Sprinkles, Tee, 必須為每個裝飾者都實現一個函數,將會出現函數爆炸,我們可以只實現一個通用的Decorator函數,通過在get_cost函數添加多個@Decorator,這很符合Decorator Pattern的思想。

def get_cost_decorator(additional_cost):
    def wrapper1(func):
        def wrapper2(instance):
            return func(instance) + additional_cost
        return wrapper2
    return wrapper1

class Coffee(object):
    @get_cost_decorator(0.5)
    @get_cost_decorator(0.7)
    @get_cost_decorator(0.2)
    def get_cost(self):
        return 1.0

coffee = Coffee()
print coffee.get_cost() #2.4

上面的get_cost_decorator類看上去比較複雜,不要緊,一會再回頭看這個函數。

Decorators基礎

閑話不多說,先看下面的簡單例子:

def myDecorator(func):
    def newFunction():
        print "inside newFunction"
        func()
    return newFunction

@myDecorator
def aFunction():
    print "inside aFunction()"

aFunction()

最終輸出:

inside newFunction
inside aFunction()

我們看到,myDecorator函數的參數其實是aFunction的函數地址,並且返回一個函數地址,返回的函數才是最終真正調用的地址。最終的調用,等價於:

aFunction = myDecorator(aFunction)
aFunction()

其中,myDecorator也可以使用class來實現,比如:

class myDecorator(object):
    def __init__(self, func):
        self.func = func
    def __call__(self):
        print "inside myDecorator"
        self.func()
@myDecorator
def aFunction():
    print "inside aFunction()"

最終,

aFunction()

相對於

aFunction = myDecorator(aFunction)
aFunction() # __call__

Decorators調用規律

上面的例子,我們可以很容易的得到這樣一個規律:

@A
def f ():
    …

最終等價於:

f = A(f)

如果更複雜一些:

@A
@B
@C
def f ():
    …

則相對於:

f = A(B(C(f)))

再看看有參數的例子,

@A(args)
def f ():
    …

這時,f相當於:

_deco = A(args)
f = _deco(f)

因此,A的實現也會相對複雜一些:

def A(args):
    def wrapper1(f):
        def wrapper2():
             print “before call f()”
             f()
        return wrapper2
    return wrapper1

有點繞吧,嗯,還算簡單,我們回頭看最開頭那個例子,

@get_cost_decorator(0.5)
@get_cost_decorator(0.7)
@get_cost_decorator(0.2)
def get_cost(self): 
    return 1.0

相當於:

get_cost =  get_cost_decorator(0.5)(get_cost_decorator(0.7)(get_cost_decorator(0.2)(get_cost)))  # 繞暈了~~

Decorators典型應用 – singleton classdef singleton(cls):
    instances = {}
    def getinstance():
        if cls not in instances:
            instances[cls] = cls()
        return instances[cls]
    return getinstance

@singleton
class MyClass:
    ...

參考文章:

Decorators for Functions and Methods

Introduction to Python Decorators 

Decorator pattern 

[Python學習]decorator的使用  - limodou

 

Python 天天美味系列(總)

Python 天天美味(30) - python資料結構與演算法之快速排序 

Python 天天美味(31) - python資料結構與演算法之插入排序 

Python 天天美味(32) - python資料結構與演算法之堆排序 

Python 天天美味(33) - 五分鐘理解元類(Metaclasses)[轉]

Python 天天美味(34) - Decorators詳解

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.