Python入門(九) 函數-閉包

來源:互聯網
上載者:User

標籤:

    在Python中,函數也是一種變數類型,也就是說可以用變數去儲存一個函數。

def hello():    print("hello")print(type(hello))>>> <class ‘function‘>

#將函數對象賦值為變數func,此時func指向了hello指向的函數對象func = hellofunc() #調用函數>>> hello

    通過上面可以看出,我們可以把一個函數賦值為一個變數,那麼此變數就指向該函數對象。當然,我們也是可以修改hello執行的函數對象的,如:

def say_hi():    print("Hi")    hello = say_hihello()>>> Hi

    把say_hi函數對象賦值為hello,那麼hello就指向了say_hi函數對象,不再指向原先的函數對象了,也就無法再調用原先的函數對象。

    基於函數的上述特性,我們可以很容易的實現一個函數功能表,比如我們常見的http的服務隊請求的處理,會根據請求的方法分別處理:

def handle_http_get():    print(‘handle http get request‘)def handle_http_post():    print(‘handle http post request‘)def handle_http_put():    print(‘handle http put request‘)http_handler = {‘get‘: handle_http_get, ‘post‘: handle_http_post, ‘put‘: handle_http_put}#上面分別實現了處理http的get,post,put請求#當請求的方法為get時,我們可以這麼處理:method = ‘get‘http_handler[method]()>>> handle http get request

    2.閉包Closure

    既然函數是對象,那麼就可以在函數中返回一個函數對象:

def get_func():    def func():        print(‘inside func‘)    return funcf = get_func() # 此時f指向了func函數對象f() #執行func函數對象>>> inside func

    一個函數與它的環境變數結合在一起,就構成Closure。

def power_factory(n):    def power(list_arg):        for i in range(len(list_arg)):            list_arg[i] = list_arg[i]**n    return power#計算list中的每個數的平方list1 = [1, 2, 3]f1 = power_factory(2)f1(list1)print(list1)f1(list1)print(list1)#計算List中每個數的立方list1 = [1, 2, 3]f2 = power_factory(3)f2(list1)print(list1)>>> [1, 4, 9][1, 16, 81][1, 8, 27]

    對於power函數對象而言,power_factory函數傳遞的參數n就是其環境變數,會儲存到函數對象的__closure__屬性中。這樣子每次調用f1函數,執行的都是2的平方操作,所以上面連續兩次調用f1,輸出的都是平方數。如果我們需要執行立方操作,只需要重新調用power_factory,產生一個環境變數n = 3的閉包。

    一般來說,像c編程中的函數,是沒有狀態的,除非在c函數中使用static變數來儲存其狀態,而使用閉包,我們可以很方便的做到函數都有其自己獨立的環境變數。

    3. 裝飾器

    函數對象有一個__name__屬性,表示函數的名字:

print(max.__name__)>>> max

    如我們前面已經實現了一個hello函數,現在我們想增強hello函數的功能,在執行hello函數前,加入列印調試資訊。在不改變hello函數源碼的前提下,可以通過閉包來完成。

def debug(func):    def wrapper(*args, **kw):        print(‘call %s‘ % func.__name__)        return func(*args, **kw)    return wrapperhello = debug(hello)hello()>>> call hellohello

    在上述的使用過程中,需要先執行hello = debug(hello), 感覺代碼總是有點怪怪的,為此Python中引入@文法,簡化使用的過程。

@debugdef hello():    print(‘hello‘)    hello()>>>call hellohello

    把@debug放在hello的前面,就相當於執行了hello = debug(hello)

    如果需要在debug中傳遞參數,則需要使用3層函數定義:

def debug(text):    def decorator(func):        def wrapper(*args, **kw):            print(‘%s: call %s‘ % (text, func.__name__))            func(*args, **kw)        return wrapper    return decorator@debug(‘debug_info‘)def hello():    print("hello")hello()>>>debug_info: call hellohello

    把@debug(‘debug_info‘)放在hello的前面,相當於執行了hello = debug(‘debug_info‘)(hello)

    

    總算寫完了,困了,睡覺了。




Python入門(九) 函數-閉包

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.