目錄python
秉承着一切皆對象的理念,咱們再次回頭來看函數(function)。函數也是一個對象,具備屬性(可使用dir()查詢)。做爲對象,它還能夠賦值給其它對象名,或者做爲參數傳遞。git
# 變量能夠被傳遞 name = 'jason' x = name print(x) # jason print(id(name), id(x)) # 3085464224688 3085464224688
# 嘗試函數像變量同樣被傳遞 def func(): print('from func') print(func) # <function func at 0x0000016E5E062E18> f = func # 其實指向的也是函數func 指向的函數體代碼的內存地址 print(f) # <function func at 0x000001B4D0D92E18> f() # from func print(id(func), id(f)) # 3085463137816 3085463137816
def func(): print("from func") def index(args): print(args) args() # 函數主要必定義(先定義)就能夠在任意地方調用 print("from index") index(func) # <function func at 0x000001B7429A2E18> # from func # from index
def index(): print('index') def func(): print('func') return index res = func() # 將返回的函數名index 賦值給變量res # func print(res) # <function index at 0x000001EF64362E18> res() # index
def func(): print('func') l = [1, 2, func, func()] # 定義的時候默認執行了func(),因此下面先打印了 func # func # func函數沒有返回值,因此默認是None print(l) # [1, 2, <function func at 0x0000013931C92E18>, None]
函數對象小練習app
def register(): print("註冊了") pass def login(): print("登陸了") pass def shopping(): print("購物了") pass def output_func_list(): print("----- 請選擇功能!") for key in func_list: print(f"---- {key}.{func_list[key][1]}") func_list = { 0: [register, '註冊'], 1: [login, '登陸'], 2: [shopping, '購物'], } while True: output_func_list() chose_func = input("請輸入功能編號(q 退出系統):").strip() if chose_func.isdigit(): # 執行相應功能 chose_func = int(chose_func) # 判斷輸入的編號在不在功能列表裏 if chose_func in func_list: func_list[chose_func][0]() # 取到功能函數名,加括號調用 else: print("您輸入的功能編號不存在,請從新輸入!") elif chose_func.lower() in ['q', 'quit']: print("感謝您的使用,祝您生活愉快~") break else: print("請正確輸入數字!")
函數的嵌套調用: # 在函數內部調用其餘函數函數
def index(): print('index') def func(): index() # 在定義 func 函數的時候不會直接調用 index 的方法 --> 函數定義的時候不執行代碼 print('func') func() # index # 經過 func()函數內部調用了index() 函數,打印出了 index # func
函數的嵌套調用能夠將複雜的邏輯簡單化測試
小練習:寫一個能夠求四個數中的最大值ui
def my_max(x, y): if x > y: return x return y def my_max4(a, b, c, d): res = my_max(a, b) res = my_max(res, c) res = my_max(res, d) return res print(my_max4(1, 5, 7, 1)) # 7
def outer(): x = 1 print("outer") def inner(): print("inner") inner() # inner() # 會報錯,在外部沒法訪問內部內容 outer() # outer # inner
實如今外部調用 outer函數的內部函數 innercode
# 想在外部調用inner 可經過把內部的函數名當作外部函數的返回值來返回給外部 def outer(): x = 1 print("outer") def inner(): print("inner") return inner # 把 inner 函數當作函數的返回值返回給 outer函數的調用者 res = outer() # outer res() # 變相調用inner # inner 實現代碼
名稱空間: # 存放的是變量名 與 變量值 的內存地址 綁定關係的地方 ,後文可能稱之爲命名空間。對象
訪問變量的值: # 要想訪問一個變量的值,必須先去名稱空間拿到對應的名字,才能訪問變量的值生命週期
命名空間分爲:內置名稱空間,全局名稱空間,局部名稱空間 三大類ip
內置名稱空間: # python 解釋器提早已經定義好了的名字(已經存放到了內置名稱空間中了)
print("hello world") max(1, 44, 62, 15) len('26515f1asfafqw') sum([1, 2, 3, 4, 5]) # 像上面的print max len sum 並無定義就能夠值使用,它們就是python解釋器提早定義好了的函數,屬於內置命名空間的
全局命名空間:文件級別的代碼
x = 1 if x == 1: y = 2 print(y) # 2 for i in [1, 2]: print(i) print(i) # 1 # 2 # 2 # 上面的 x y z 都在全局名稱空間,不要覺得縮進的就是局部的(if、 for、 while 不管嵌套,多少層,他們內部所建立的名字都是全局名稱空間的)
局部命名空間: (目前所學)函數體內建立的名字都屬於局部名稱空間(最外層的函數名是屬於全局名稱空間的)
def func(): username = 'jason' # print(username) # 會報錯 NameError: name 'username' is not defined func()
至於爲何上面的 print(username) 爲何會報錯,學完下面的知識你就知道啦。
''' 名稱空間的生命週期 內置名稱空間:(最長)只要 python解釋器啓動,立馬建立 關閉 python解釋器時自動銷燬 全局名稱空間: 只要右鍵運行 py文件就會自動建立 py文件程序運行結束自動銷燬 局部名稱空間:(動態建立動態銷燬)函數被調用的時候自動建立 函數執行結束後當即銷燬 '''
''' # 名稱空間生命週期結束 -- > 裏面存的變量與指向值的內存地址解綁,內存中的值等待垃圾回收機制回收 # def 刪除變量 -- > 裏面存的變量與指向值的內存地址解綁,內存中的值等待垃圾回收機制回收 ---> 等同於名稱空間裏刪除了一個變量(綁定關係) # 垃圾回收機制:垃圾回收機制隔一段時間就會檢查一次,內存中的值若是沒有變量指向它(引用),那垃圾回收機制就會把它清除掉(釋放內存) # 若是屢次檢查都有變量等指向它,那就會把它等級提高,檢查頻率就會變低 '''
驗證思路: # 找一個三個地方都有的東西來驗證(好比 len、max等,暫時忽略命名規範不能與關鍵字重複) , # 分別註釋來測試其查找順序(全局、局部 )
len = '我是全局名稱空間的len' def func(): len = '我是局部名稱空間的len' print(len) print(len) # 這裏是全局的位置 # 我是全局名稱空間的len ''' # 把全局的len 註釋掉,就去找了內置的len print(len) # 是全局的位置 # <built-in function len> ''' func() # 我是局部名稱空間的len
''' (******)名稱空間的查找順序 1.須要先肯定當前的在哪(全局、局部),大前提 1.1 站在全局:全局 >>> 內置 1.2 站在局部:局部 >>> 全局 >>> 內置 1.2.2 站在局部的內部(多個局部嵌套):局部 >>> 上一級局部 >>> 上一級局部 >>> .... >>> 全局 >>> 內置 會在做用域同級的先後(這句代碼先後的同級語句)去找,而後再上一級 2.函數在定義階段查找名字的順序(範圍)就已經固定了, 不會由於函數的調用位置變化而變化(*******) 能夠在函數定義的時候寫個註釋,指出他查找的位置,防止邏輯複雜了搞不清楚 '''
python中的做用域有 全局做用域 與 局部做用域 , 全局做用域: # 全局有效: 內置名稱空間、全局名稱空間 都屬於全局做用域 , 局部做用域: # 局部有效:局部名稱空間
# 嘗試修改不可變類型的全局變量 x = 1 def func(): x = 2 # 實質是又建立了一個局部變量 x func() print(x) # 局部沒法修改不可變類型的全局變量 # 1 # 嘗試修改可變類型的局部變量 x = [] def func(): x.append('嘿嘿嘿') func() print(x) # 修改爲功,局部能夠修改可變類型的全局變量 # ['嘿嘿嘿'] # 全局訪問不了局部的變量,因此不展開研究
小結論: # 局部沒法修改不可變類型的全局變量 , # 局部能夠修改可變類型的全局變量 (前提:在不使用 global 和 nonlocal 關鍵字的狀況下)
經過 global 關鍵字在局部修改全局,修改多個用 , 隔開
x = 1 # 不可變類型 username = 'jason' def func(): global x,username x = 999 # 修改全局變量,而不是建立局部變量 username = 'egon' func() print(x, username) # 999 egon
經過 nonlocal 關鍵字在局部修改局部,修改多個用 , 隔開
def func(): x = 1 def index(): x = 2 index() print(x) func() # 1 # 想就在 index 裏把 x 改了 def func(): x = 1 def index(): nonlocal x x = 2 index() print(x) func() # 2