函數對象
在面向對象編程中 一切皆對象
具體的體現
1.函數可以被引用
2.函數可以作為函數的參數
3.函數可以作為函數的返回值
4.可以被存儲到容器類型中
def pay(): print('支付') def save(): print('存錢') def cheak(): print('查看') dic={'1':pay,'2':save,'3':cheak} while True: l=['支付','存錢','查看'] for i,k in enumerate(l): print(i+1,k) cmd=input('>>>:') if cmd in dic: dic[cmd]() else: print('指令錯誤')
2.函數嵌套
1.嵌套調用 在一個函數中調用了另一個函數
2.嵌套定義 在一個函數中定義了另一個函數
定義在函數內的函數 只能函數內使用 外界不能訪問
def func1(): print("func1") def func2(): print("func2") func1() func2()
def func1(): print("func1") def func2(): print("func2") func2() func1()
3.函數的名稱空間
存儲名稱的空間
名稱空間的分類
內置名稱空間 存儲解釋器自帶的一些名稱與值的對應關系
(python解釋器啟動時創建 所有代碼全部執行完畢 關閉解釋器時 銷毀)
print len max min
全局名稱空間 哪些數據會存儲在全局空間?
文件級別的名稱 只要你的名字的定義是頂著最左邊寫的就在全局空間
除了內置的函數內的 都在全局中
(執行py文件創建全局名稱空間 關閉解釋器時 銷毀)
局部名稱空間 只要是函數內的名稱就是局部的
(調用函數時創建 函數執行完畢就銷毀)
名稱空間的加載順序
內置的 -> 全局的 ->局部的
名稱的查找順序
局部 -> 全局的 -> 內置的
4.函數的作用域
作用域(作用范圍)
域 指的是區域 范圍的的意思
全局的名稱空間和內置的名稱空間 在使用上沒什么區別
局部的和全局的內置的 就區別了 局部定義的只能在局部使用
給三個空間劃分范圍
全局的和內置可以劃分為同一個范圍
global 表示的全局范圍 就是所謂的全局作用域
局部的單獨劃分為一個范圍
local 局部作用域
globals()
locals()
print(locals())#查看全局作用域,當locals在全局作用域時,功能和globes相同 print(globals()) def func(): a = 100 print(locals())#查看局部作用域 func()
age = 18 def func2(): # 明確聲明 要使用全局中的age global age age = 19 print(age) func2() print(age)
a = 1 def func3(): a = 10 def inner(): # 明確聲明 要使用上一中的 a 如果上一層沒有 則找上上層 但是注意 不能找到全局中的 nonlocal a a = 100 print(a) inner() print("這是func3中a",a) func3() print(a)
5.閉包函數
age = 20 # 如下就是一個閉包函數 def fun1(): age = 18 def inner(): print("hello") print(age) # 在返回這個內部的函數時 不是單純的返回函數 還把函數中訪問到的局部名稱一起打包了 # 相當于將內部函數與 訪問的數據打包在一起了 閉包這個名字就是這么得來的 return inner f = fun1() # f 就是inner f() # 函數的作用域在定義時就固定了 與調用沒有關系
# 閉包函數的模板 def func2(): a = 1 b = 10 def inner(): print(a) print(b) return inner
什么是閉包函數
1.定義在另一個函數內的函數
2.內部的的函數訪問了外部的名稱數據 注意 不包含全局的)
6.裝飾器
什么是裝飾器
什么是裝飾 給一個已有的對象(一個函數) 添加新的功能
為什么要裝飾 增強功能
器 指一個工具 在python中 值得是具備某個功能的函數
簡單的說:裝飾器就是 一個用于給其他函數增加功能的函數
import time def download(): print('開始下載xxx.mp4') time.sleep(2) print('xxxx.mp4 下載完成') # 請你統計下載耗時 start_time = time.time() download() end_time = time.time() print('下載耗時',(end_time-start_time)) def download2(): start_time = time.time() print("開始下載xxx.mp4") time.sleep(2) print("xxxx.mp4 下載完成!") end_time = time.time() print("下載耗時", (end_time - start_time)) download2()
def max2(x,y): if x > y: return x else: return y res=max2(10,20) x=10 y=20 # res=x if x > y else y # print(res) res='OK' if False else 'No' print(res)
def outter(func): def inner(): strat_time = time.time() func() end_time = time.time() print('下載耗時',(end_time-start_time)) return inner download=outter(download) download()
# 疊加多個裝飾器 # 1. 加載順序(outter函數的調用順序):自下而上 # 2. 執行順序(wrapper函數的執行順序):自上而下 def outter1(func1): #func1=wrapper2的內存地址 print('加載了outter1') def wrapper1(*args,**kwargs): print('執行了wrapper1') res1=func1(*args,**kwargs) return res1 return wrapper1 def outter2(func2): #func2=wrapper3的內存地址 print('加載了outter2') def wrapper2(*args,**kwargs): print('執行了wrapper2') res2=func2(*args,**kwargs) return res2 return wrapper2 def outter3(func3): # func3=最原始的那個index的內存地址 print('加載了outter3') def wrapper3(*args,**kwargs): print('執行了wrapper3') res3=func3(*args,**kwargs) return res3 return wrapper3 @outter1 # outter1(wrapper2的內存地址)======>index=wrapper1的內存地址 @outter2 # outter2(wrapper3的內存地址)======>wrapper2的內存地址 @outter3 # outter3(最原始的那個index的內存地址)===>wrapper3的內存地址 def index(): print('from index') print('======================================================') index() '''
import time current_user={'user':None} def auth(engine='file'): def outter(func): def wrapper(*args,**kwargs): if current_user['user']: res=func(*args,**kwargs) return res user=input('username>>>: ').strip() pwd=input('password>>>: ').strip() if engine == 'file': # 基于文件的認證 if user == 'egon' and pwd == '123': print('login successfull') current_user['user']=user res=func(*args,**kwargs) return res else: print('user or password error') elif engine == 'mysql': # 基于mysql的認證 print('基于mysql的認證') elif engine == 'ldap': # 基于ldap的認證 print('基于ldap的認證') else: print('不知道engine') return wrapper return outter @auth('ldap') #@outter #index=outter(index) # index=wrapper def index(): time.sleep(1) print('from index') @auth('mysql') #@outter # home=outter(home) #home=wrapper def home(name): print('welcome %s' %name) index() home('egon')
def max2(x,y): if x > y: return x else: return y res=max2(10,20) x=10 y=20 # res=x if x > y else y # print(res) res='OK' if False else 'No' print(res)
# 列表生成式 # l=[] # for i in range(10): # if i > 4: # l.append(i**2) # # # # l=[i**2 for i in range(10) if i > 4] # print(l) # names=['egon','alex_sb','kevin_sb','hxx_sb','cxx_sb'] # sbs=[] # for name in names: # if name.endswith('sb'): # sbs.append(name) # sbs=[name.upper() for name in names if name.endswith('sb')] # print([name.upper() for name in names]) # print([name for name in names if name.endswith('sb')]) # 字典生成式 # res={i:i**2 for i in range(10) if i > 3} # print(res)
# func() # func() # func() # 匿名函數就是只定義了一個函數的內存地址,主要用于臨時使用一次的場景 # func=lambda x,y:x+y # print(func) # print(func(1,2)) # res=(lambda x,y:x+y)(1,2) # print(res) # print(max([10,11,-3,23])) # salaries={ # 'egon':3000, # 'alex':100000000, # 'wupeiqi':10000, # 'yuanhao':2000 # } # def func(k): # return salaries[k] # print(max(salaries,key=lambda k:salaries[k])) # print(min(salaries,key=func)) # for循環的結果 比較依據 # 'egon' 3000 # 'alex' 100000000 # 'wupeiqi' 10000 # 'yuanhao' 2000 # l=[4,2,3] # l_new=sorted(l,reverse=True) # print(l_new) # # # print(sorted(salaries,key=lambda k:salaries[k],reverse=True)) #
迭代器
1. 什么是迭代器
什么是迭代?
迭代是一個重復的過程,但是每次重復都是基于上一次重復的結果而繼續
#下列循環知識單純的重復
while True:
print(1)
# 基于索引的迭代取值
l=['a','b','c']
i=0
while i < len(l):
print(l[i])
i+=1
什么是迭代器?
迭代取值的工具
2. 為什么要用迭代器
迭代器
優點
1. 提供一種不依賴索引的迭代取值方式
2. 更節省內存
缺點:
1. 不如按照索引的取值方式靈活
2. 取值一次性的,只能往后取,無法預測值的個數
3. 如何用迭代器
可迭代的對象:str\list\tuple\dict\set\文件對象
但凡內置有__iter__方法的對象都稱之為可迭代對象
迭代器對象: 文件對象
既內置有__iter__方法又內置有__next__方法的對象都稱之為迭代器對象
調用可迭代對象下__iter__方法,會有一個返回值,該返回值就是內置的迭代器對象
# s='abcdef' # l=['a','b','c'] # d={'k1':111,'k2':222,'k3':333} # iter_d=d.__iter__() # # print(iter_d) # # try: # print(iter_d.__next__()) # print(iter_d.__next__()) # print(iter_d.__next__()) # print(iter_d.__next__()) # except StopIteration: # print('取值完畢') d={'k1':111,'k2':222,'k3':333} # d={1,2,3,4,5} # d=[1,2,3,4] # iter_d=d.__iter__() # iter_d=iter(d) #d.__iter__ # print(next(iter_d)) #iter_d.__next__() # print(len(d)) print(d.__len__()) # print(iter_d.__iter__().__iter__().__iter__() is iter_d) # print(d.__iter__().__next__()) # print(d.__iter__().__next__()) # print(d.__iter__().__next__()) # while True: # try: # v=iter_d.__next__() # print(v) # except StopIteration: # break # # print('第二次取值') # # iter_d=d.__iter__() # while True: # try: # v=iter_d.__next__() # print(v) # except StopIteration: # break # # for k in d: # print(k) #for循環的底層原理: # 1. 調用in后面那個值/對象的__iter__方法,拿到一個迭代器對象iter_obj # 2. 調用迭代器對象iter_obj.__next__()將得到的返回值賦值變量名k,循環往復直到取值完畢拋出異常StopIteration # 3. 捕捉異常結束循環
生成器就是一種自定義的迭代器
如何得到生成器?
但凡函數內出現yield關鍵字,再去調用函數不會立即執行函數體代碼,會得到一個返回值,該返回值就是生成器對象,
即自定義的迭代器
# def func(): # print('first') # yield 1 # print('second') # yield 2 # print('third') # yield 3 # # # g=func() # # print(g) # # res1=next(g) # print(res1) # # res2=next(g) # print(res2) # # res3=next(g) # print(res3) # # next(g) # 總結yield: # 1. 提供一種自定義迭代器的解決方案 # 2. yield & return # 相同點: 都可以返回值,返回值沒有類型限制\個數限制 # 不同點: return只能返回一次值,yield卻可以讓函數暫停在某一個位置,可以返回多次值 # def my_range(start,stop,step=1): # while start < stop: # 5 < 5 # yield start # 3 # start+=step #start=5 # range(1,5,2) # 1 3 # for i in my_range(1,5000000000000000000000000000000000000000000,2): # 1 3 # print(i)
函數的遞歸調用與二分法
1. 函數的遞歸調用:
在調用一個函數的過程又直接或者間接地調用該函數本身,稱之為遞歸調用
遞歸必須滿足兩個條件:
1. 每進入下一次遞歸調用,問題的規模都應該有所減少
2. 遞歸必須有一個明確的結束條件
遞歸有兩個明確的階段:
1. 回溯
2. 遞推
# age(5)=age(4)+2 # age(4)=age(3)+2 # age(3)=age(2)+2 # age(2)=age(1)+2 # age(1)=18 # age(n)=age(n-1)+2 # n > 1 # age(1)=18 # n = 1 # def age(n): # if n == 1: # return 18 # return age(n-1)+2 # # print(age(5)) # l=[1,[2,[3,[4,[5,[6,[7,[8,[9,]]]]]]]]] # # def func(list1): # for item in list1: # if type(item) is not list: # print(item) # else: # # 如果是列表,應該... # func(item) # # func(l) # nums=[3,5,7,11,13,23,24,76,103,111,201,202,250,303,341] # # find_num=203 # for num in nums: # if num == find_num: # print('find it') # break # else: # print('not exists') nums=[3,5,7,11,13,23,24,76,103,111,201,202,250,303,341] def binary_search(list1,find_num): print(list1) if len(list1) == 0: print('not exist') return mid_index=len(list1) // 2 if find_num > list1[mid_index]: # in the right binary_search(list1[mid_index + 1:],find_num) elif find_num < list1[mid_index]: # in the left binary_search(list1[:mid_index],find_num) else: print('find it') binary_search(nums,203)
res=[i for i in range(10) if i > 5]
print(res)#這是列表生成式
g=(i for in range(10) if i >5)
print(g)
print(next(g))
print(next(g))
print(next(g))
print(next(g))#這是生成器表達式
with open('a.txt','rt,encoding='utf8')as f: #print(len(f.read())) 統計文件中字符個數 res = sum(len(line) for line in f) print(res) #用生成器表達式的方法統計文件字符個數
浙公網安備 33010602011771號