1、函數對象python
函數是第一類對象:函數名指向的值能夠被當作參數傳遞函數
1.函數名能夠被傳遞spa
def func(): print('from func') f = func #函數名能夠被傳遞,這裏用一個變量名賦值 func() #from func print(f) #這裏打印的是函數的內存地址 f() #f()等價於 func()
2.函數名能夠被當作參數傳遞給其餘函數code
def func(): print('from func') def index(args): print(args) #等價於print(func) 打印函數func內存地址 args() #運行函數func() 執行內部代碼 print('from index') index(func) #函數名func當作參數名傳遞到index函數中 #結果 #<function func at 0x0000001A50EE0E18> #from func #from index
3.函數名能夠被當作函數的返回值對象
def index(): print('index') def func(): print('func') return index res = func() #返回值是 index print(res) #打印函數名index的內存地址 res() #調用運行index()函數 #結果 #func #<function index at 0x0000001DB2490E18> #index
4.函數名能夠被當作容器類型的參數blog
def func(): print('func') print(func()) #func None l = [1,2,func,func()] print(l) #結果 func None func #爲何結果有這個,由於在l調用了函數func(),因此打印一個func [1, 2, <function func at 0x0000009769AF0E18>, None]
2、函數調用 (在一個函數內部調用其餘函數,能夠將複雜的邏輯簡單化)生命週期
def index(): func() print('index') def func(): print('func') index() #調用index()以後,func()已經被定義了,能夠被調用
3、名稱空間內存
名稱空間是什麼:就是存放變量名和變量值的內存地址的綁定關係的地方作用域
名稱空間的分類:io
1.內置空間名稱:python解釋器提早給你定義好的名字(已經存放在內置名稱空間了)
就是一些內置函數:好比 len()/max()....
2.全局名稱空間:文件級別的代碼
3.局部名稱空間:函數體內建立的名字都屬於局部名稱空間
def func(): username = 'jason' #這個username是局部名稱空間 print(username) func()
總結:生命週期
內置名稱空間:只要python解釋器已啓動立馬建立 關閉python解釋器的時候內置名稱空間自動銷燬(針對於python解釋器)
全局名稱空間:只要你運行py文件的時候會自動建立 py文件程序運行結束自動銷燬 (針對於py文件)
局部名稱空間:函數被調用的時候建立 函數結束就銷燬(針對於函數的調用開始結束)
4、名稱空間的查找順序
注意:先要肯定好你當前在哪(在哪一個空間)
查找順序
1.若是你如今在全局: 全局 >>>內置 (先從全局找再到內置)
2.若是你如今在局部:局部>>全局>>內置(先從局部找再到全局再到內置)
例題:
局部命名空間:先定位要打印的len屬於什麼空間,由於它是在函數裏面的變量,因此它是局部名稱空間,先找局部變量,正好函數裏面有一個變量名賦值,因此這個len就從這取值
len = '我是全局名稱空間的len' def func(): len = '我是局部名稱空間的len' print(len) func()
全局和局部:咱們先來看紅色的len,這個len在全局的位置,查找順序先從全局開始,不會找到函數內部的局部。在全局裏面已經有一個定義的len,因此用這個 '我是全局名稱空間的len'。而後函數裏面的len就和上面的同樣了。
len = '我是全局名稱空間的len' def func(): len = '我是局部名稱空間的len' print(len) print(len) # 我如今站在的是全局的位置 func()
#結果
#我是全局名稱空間的len
#我是局部名稱空間的len
局部:打印的x在局部位置,在自己函數沒有,因此就往上一個找局部,找到有一個x。
def func(): x = 1 def index(): print(x) # 1 return index res = func() x = 999 res()
全局:若是把上一道題的局部x刪掉,就要到全局裏面找,找到x=999在函數調用以前已經定義了,最後結果就是999
def func(): def index(): print(x) # 999 return index res = func() x = 999 res()
全局:x定位到局部,可是在inner裏面找不到,outer裏面也找不到,因此x是使用全局,後面的inner在哪裏調用,x都是在全局找值
x=111 def outer(): def inner(): print('from inner',x) #from inner 111 return inner f=outer() def func(): x=333 f() func()
總結:函數在定義階段就已經固定查找名字的順序了,不會由於函數調用的位置改變而改變
5、做用域
做用域就是做用範圍,按照生效範圍能夠分爲全局做用域和局部做用域
全局做用域:包含內置名稱空間、全局名稱空間,在整個文件的任意位置都能被引用,全局有效
局部做用域:局部名稱空間、只能在局部範圍生效
global和nonlocal
global:在局部修改全局的不可變數據類型
在下面這個若是不是用global,後面x和username打印的全局的值,就是1,jason。若是你使用了global,改變了全局變量的值,在下面設置x = 999,username = 'egon',打印的值也是這個。
nonlocal:局部修改局部(函數嵌套)
若是沒有加nonlocal,x在局部找值,x=1。nonlocal 修改了前面x的值,在打印的時候變成2
總結:global:局部修改全局,若是有多個,用逗號隔開
nonlocal:局部修改局部,若是有多個,用逗號隔開