1. 程式人生 > >python函數下篇裝飾器和閉包,外加作用域

python函數下篇裝飾器和閉包,外加作用域

發揮 作用域 fat 功能 user div 日誌 code 返回函數

裝飾器和閉包的基礎概念

裝飾器是一種設計模式能實現代碼重用,經常用於查日誌,性能測試,事務處理等,抽離函數大量不必的功能。 裝飾器:
1、裝飾器本身是一個函數,用於裝飾其它函數:
2、功能:增強被裝飾函數的功能。

裝飾器需要遵循的原則

1.不修改被裝飾函數的源代碼(開放封閉原則) 2.為被裝飾函數添加新功能後,不修改被裝飾函數的調用方式

裝飾器 = 高階函數+函數嵌套+閉包

高階函數

1.函數接受的參數是一個函數名 2.函數的返回值是一個函數名 3.只有上述條件滿足一個就是高階函數

def foo():
    print(高階函數實例,被調用的函數)

def func(foo):
    
print(調用上面的函數) foo() func(foo)

把函數名當做參數傳給告誡函數,告誡函數直接返回函數名

import time
def foo():
    print(from the foo)

def timmer(func):
    start_time = time.time()
    return func
    stop_time = time.time()
    print(函數%s運行時間是%s)%(func,stop_time - start_time)

foo = timmer(foo)
foo()

高階函數總結 1.函數接收的參數是一個函數名
作用:在不修改函數源代碼的前提下,為函數添加新功能
不足:會改變函數的調用方式

2.函數的返回值是一個函數名
作用:不修改函數的調用方式
不足:不能添加新功能

嵌套函數

def father(name):
    print(from father %s%name)
    def son():
        print(from son)
        def grandson():
            print(from grandson)
        grandson()
    son()
father(逗逼)

閉包函數:函數在嵌套環境中,如果在內層函數裏,對外層函數作用域中的變量進行引用,在外層函數返回後內層函數依然可以使用外層函數中的變量,這種變量就構成了內層函數可以使用的環境。所以閉包對隱藏狀態,以及在函數對象和作用域中隨意切換,一個函數可以發揮N種功用

def f1(x):
def f2(y):
return y ** x
return f2
f1(4)

f3=f1(3)
type(f3)

f3(4)

def startPos(m,n):
def newPos(x,y):
print(‘‘The old position is (%d,%d), and the new position is (%d,%d)"%(m,n,m+x,n+y))
return newPos

action = startPos(10,10)
action(1,2)
action(-1,3)

#結果
<function f1.<locals>.f2 at 0x02125270>
<class function>
64
The old position is (10,10),and the new position is (11,12)
The old position is (10,10),and the new position is (9,13)

無參裝飾器

無參裝飾器 = 高級函數 + 函數嵌套 基本框架

#這就是一個實現一個裝飾器最基本的架子
def time(func):
    def wrapper():
        func()
    return wrapper

加上參數

def timer(func):
    def wrapper(*args,**kwargs):
        func(*args,**kwargs)
    return wrapper

加上功能

import time
def timer(func):
    def wrapper(*args,**kwargs):
        start_time = time.time()
        func(*args,**kwargs)
        stop_time = time.time()
        print(函數[%s],運行時間是[%s]%(func,stop_time-start_time))
    return wrapper

加上返回值

import time
def timer(func):
    def wrapper(*args,**kwargs):
        start_time = time.time()
        res = func(*args,**kwargs)
        stop_time = time.time()
        print(函數[%s],運行時間是[%s]%(func,stop_time-start_time))
        return res
    return wrapper

使用裝飾器

def cal(arry):
    res = 0
    for in in array:
        res+=i
    return res
cal = timer(cal)
cal(range(10)

語法糖@

@timer 
def cal()
    def cal(array):
      res=0
      for i in array:
          res+=i
      return res
 
  cal(range(10))

有參裝飾器

user_list=[
    {name:alex,passwd:123},
    {name:linhaifeng,passwd:123},
    {name:wupeiqi,passwd:123},
    {name:yuanhao,passwd:123},
]
current_user={username:None,login:False}
def auth(auth_type=file):
    def auth_deco(func):
        def wrapper(*args,**kwargs):
            if auth_type == file:
                if current_user[username] and current_user[login]:
                    res = func(*args,**kwargs)
                    return res
                username = input(用戶名:).strip()
                passwd = input(密碼:).strip()
                for index,user_dic in enumerate(user_list):
                    if username == user_dic[name] and passwd ==username[passwd]:
                        current_user[username] =username
                        current_user[login]=True
                        res = func(*args,**kwargs)
                        return res
                        break
                else:
                    print(用戶名或者密碼錯誤,重新登錄)
            elif auth_type ==ldap:
                print(登錄成功)
                res = func(*args,**kwargs)
                return res
        return wrapper
    return auth_deco
@auth(auth_type=ldap)
def index():
    print(歡迎來到主頁面)
@auth(auth_type=ldap)
def home():
    print(家目錄)
def shopping_car():
    print(購物車頁面)
def order():
    print(訂單頁面)
index()
home()

作用域規則 每次執行執行一個函數時,就會創建新的局部命名空間。該命名空間代表一個局部環境,其中包含函數參數的名稱和在函數體內賦值的變量名稱。解析這些名稱 時,解釋器首先搜索局部命名空間、如何沒有找到匹配的名稱,它就會搜索全局命名空間。函數的全局命名空間始終是定義該函數的模塊。如果解釋器在全局命名空間中也找不到匹配值,最終會檢查內置命名空間。如果仍然找不到,就會引發NameError異常 技術分享

python函數下篇裝飾器和閉包,外加作用域