week4: 函數之裝飾器

一、裝飾器前戲之閉包

閉包是函數式編程的重要語法結構

定義:如果在一個內部函數裏,對在外部作用域(但不是在全局作用域)的變量進行引用,那麼內部函數被認爲是閉包。

def f():
    c = 5
f()
print(c)  ##NameError: name 'c' is not defined
def outer():
    x = 10
    def inner():  ##條件一 inner就是內部函數
        print(x)  ##條件二 外部環境的一個變量

    return inner   ##結論:內部函數inner就是一個閉包
f=outer()
f()  ## 10

閉包= 函數快+定義函數時的環境

二、裝飾器高潮

2.1 #遵守封閉與開放原則

import time

def foo():
    start = time.time()
    print('foo...')
    time.sleep(2)
    end = time.time()
    print('spend %s' % (end-start))

foo()  ##foo...  spend 2.0003113746643066

如果有多個函數需要計算時間,每一個函數都像上述所做,會引起代碼重複。

import time

def foo():

    print('foo...')
    time.sleep(2)

def showtime(f):
    start = time.time()
    f()
    end = time.time()
    print('spend %s' % (end-start))


showtime(foo)

但是這種方法確是改變了函數的調用方式。

import time

def foo():

    print('foo...')
    time.sleep(2)

def showtime(f):
    def inner():
        start = time.time()
        f()
        end = time.time()
        print('spend %s' % (end-start))
    return inner

foo=showtime(foo)  ##此時輸出的是inner的內存地址
foo()  ##相當於執行的是inner函數,閉包
import time

def showtime(f):
    def inner():
        start = time.time()
        f()
        end = time.time()
        print('spend %s' % (end-start))
    return inner


@showtime   ##foo=showtime(foo)  ##此時輸出的是inner的內存地址
def foo():

    print('foo...')
    time.sleep(2)
    
foo()  ##相當於執行的是inner函數,閉包

2.2 裝飾器之被裝飾函數的參數

import time

def showtime(f):
    def inner(x, y):
        start = time.time()
        f(x, y)
        end = time.time()
        print('spend %s' % (end-start))
    return inner


@showtime   ##add=showtime(add)  ##此時輸出的是inner的內存地址
def add(a, b):
    print(a+b)
    time.sleep(1)

add(1,2)  ##相當於執行的是inner函數,閉包
import time

def logger(flag=''):

    def showtime(f):
        def inner(x, y):
            start = time.time()
            f(x, y)
            end = time.time()
            print('spend %s' % (end-start))
            if flag=='true':
                print('rizhijilu')

        return inner
    return showtime

@logger('true')##先執行logger函數,==@showtime,返回函數對象的內存地址
def add(a, b):
    print(a+b)
    time.sleep(1)
add(1,2)  ##相當於執行的是inner函數,閉包


@logger('000')
def bar():
    print('bar...')
    time.sleep(2)
bar()

2.3 裝飾器應用

比如京東,第一次登陸後,之後點其他京東頁面,不需要登陸。

在裝飾器裏,一方面檢測狀態,另一方面登陸

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章