python 函數對象、函數嵌套、名稱空間與做用域

一 函數對象

一 函數是第一類對象,即函數能夠看成數據傳遞

#1 能夠被引用
#2 能夠看成參數傳遞
#3 返回值能夠是函數
#3 能夠看成容器類型的元素

二 利用該特性,優雅的取代多分支的if

def foo(): print('foo') def bar(): print('bar') dic={ 'foo':foo, 'bar':bar, } while True: choice=input('>>: ').strip() if choice in dic: dic[choice]()

二 函數嵌套

一 函數的嵌套調用

def max(x,y): return x if x > y else y def max4(a,b,c,d): res1=max(a,b) res2=max(res1,c) res3=max(res2,d) return res3 print(max4(1,2,3,4))

二 函數的嵌套定義

def f1(): def f2(): def f3(): print('from f3') f3() f2() f1() f3() #報錯,爲什麼?請看下一小節

 

三 名稱空間與做用域

一 什麼是名稱空間?

 #名稱空間:存放名字的地方,三種名稱空間,(以前遺留的問題x=1,1存放於內存中,那名字x存放在哪裏呢?名稱空間正是存放名字x與1綁定關係的地方)python

二 名稱空間的加載順序閉包

python test.py #一、python解釋器先啓動,於是首先加載的是:內置名稱空間 #二、執行test.py文件,而後以文件爲基礎,加載全局名稱空間 #三、在執行文件的過程當中若是調用函數,則臨時產生局部名稱空間

 

三 名字的查找順序

局部名稱空間--->全局名稱空間--->內置名稱空間 #須要注意的是:在全局沒法查看局部的,在局部能夠查看全局的,以下示例

# max=1
def f1(): # max=2
    def f2(): # max=3
        print(max) f2() f1() print(max)

 

四 做用域

#一、做用域即範圍
        - 全局範圍(內置名稱空間與全局名稱空間屬於該範圍):全局存活,全局有效   - 局部範圍(局部名稱空間屬於該範圍):臨時存活,局部有效 #二、做用域關係是在函數定義階段就已經固定的,與函數的調用位置無關,以下
x=1
def f1(): def f2(): print(x) return f2 x=100
def f3(func): x=2 func() x=10000 f3(f1()) #三、查看做用域:globals(),locals()
 LEGB 表明名字查找順序: locals -> enclosing function -> globals -> __builtins__ locals 是函數內的名字空間,包括局部變量和形參 enclosing 外部嵌套函數的名字空間(閉包中常見) globals 全局變量,函數定義所在模塊的名字空間 builtins 內置模塊的名字空間

 

五 global與nonlocal關鍵字

 

第一,二者的功能不一樣。global關鍵字修飾變量後標識該變量是全局變量,對該變量進行修改就是修改全局變量,而nonlocal關鍵字修飾變量後標識該變量是上一級函數中的局部變量,若是上一級函數中不存在該局部變量,nonlocal位置會發生錯誤(最上層的函數使用nonlocal修飾變量一定會報錯)。

第二,二者使用的範圍不一樣。global關鍵字能夠用在任何地方,包括最上層函數中和嵌套函數中,即便以前未定義該變量,global修飾後也能夠直接使用,而nonlocal關鍵字只能用於嵌套函數中,而且外層函數中定義了相應的局部變量,不然會發生錯誤(見第一)。函數

 

 

四 閉包函數

一 什麼是閉包?

#內部函數包含對外部做用域而非全局做用域的引用

#提示:以前咱們都是經過參數將外部的值傳給函數,閉包提供了另一種思路,包起來嘍,包起呦,包起來哇

        def counter(): n=0 def incr(): nonlocal n x=n n+=1
                return x return incr c=counter() print(c()) print(c()) print(c()) print(c.__closure__[0].cell_contents) #查看閉包的元素

 

 

二 閉包的意義與應用

#閉包的意義:返回的函數對象,不單單是一個函數對象,在該函數外還包裹了一層做用域,這使得,該函數不管在何處調用,優先使用本身外層包裹的做用域 #應用領域:延遲計算(原來咱們是傳參,如今咱們是包起來)
    from urllib.request import urlopen def index(url): def get(): return urlopen(url).read() return get baidu=index('http://www.baidu.com') print(baidu().decode('utf-8'))
相關文章
相關標籤/搜索