函數是對代碼塊和功能的封裝和定義
#函數的語法:def是define的意思,定義
最基本的語法: def 函數名(): 函數體 函數名() #調用函數
帶有參數的語法 def 函數名(形參列表): 函數體(代碼塊,return) 函數名(實參列表) :調用
#例子:函數執行過程
# def wan(): #定義函數 # print("今天一塊兒去玩") # print("去哪裏玩呢") # print("我不知道") # wan() #調用函數 '''講解執行的過程 1.定義函數wan() 2.調用函數wan() 3.準備開始執行函數 4.打印,今天一塊兒去玩 5.打印,去哪裏完 6.打印,我不知道 7.函數執行完畢,本次調用完畢,wan()函數調用完畢 '''
return:在函數執行的時候,若是遇到return,則直接返回,和while循環中break同樣 1、若是函數什麼都不寫,不寫return,沒有返回值,獲得的是Nano 2、在函數中間或者末尾寫return,返回的是None 三、在函數中寫 return 值,返回的是一個值 四、在函數中有返回多個返回值,return 值一、值二、值3... 返回接收到的是元組 #例子: #一、函數什麼都不寫,不寫return,返回的是None def wan(): print("今天一塊兒去玩") print("去哪裏玩呢") print("我不知道") ret = wan() print(ret) #None #二、在函數中間或者末尾寫return,返回的是None def wan(): print("今天一塊兒去玩") return print("去哪裏玩呢") print("我不知道") ret = wan() print(ret) #在執行完第一個print的時候就返回None,就結束了 #三、在函數中寫一個return 值,返回的是一個值 def wan(): print("今天一塊兒去玩") return "鍋蓋" print("去哪裏玩呢") print("我不知道") ret = wan() print(ret) #今天一塊兒去玩 #鍋蓋 #會看到返回鍋蓋就結束了 #四、函數中有返回多個返回值,那麼返回的是一個元組 def wan(): print("今天一塊兒去玩") return "鍋蓋","番薯","大塊" print("去哪裏玩呢") print("我不知道") ret = wan() print(ret) ##('鍋蓋', '番薯', '大塊')
函數在調用的時候指定具體的一個變量的值,就是參數
#參數包括:形參,實參,傳參python
形參:函數聲明的位置的變量
實參:函數調用的時候給的具體的值
傳參:把實參交給形參的過程
#相關參數具體位置例子面試
#形參和實參的位置 # def wan(形參): #在函數聲明的位置的變量就是形參 # print(好玩) # # wan(實參) :#在函數調用的地方給的具體的值就是實參 #例子 # def wan(what): # print("手機") # print("去哪裏"+what) # wan("廣西") #在調用wan的時候給what一個值,而後執行函數體
#實參的相關操做算法
#包括 1.位置參數:按照形參的參數位置,給形參傳值 2.關鍵字參數:按照形參的名字給形參傳值 3.混合參數:即用位置參數,也用關鍵字參數
#實參操做的例子:安全
# 一、位置參數,按照形參的位置,給形參傳值 #例子 # def chi(moning,after,night): # print(moning,after,night) # chi("玉米餃","米飯","麪條") #玉米餃 米飯 麪條 #2.關鍵字參數: 按照形參的名字給形參傳值 # def chi(moning,after,night): # # print(moning,after,night) # # chi(after="米飯",moning="餃子",night="麪條") #餃子 米飯 麪條 # 3.混合參數:即用位置參數,也用關鍵字參數 # def chi(moning,after,night): # print(moning,after,night) # chi("餃子","米飯",night="麪條") #餃子 米飯 麪條 #注意: #順序位置:要先寫位置後再寫關鍵字,要否則會報錯 #例子 # chi("餃子",night="麪條","米飯") #會報紅色 #SyntaxError: positional argument follows keyword argument #語法錯誤:關鍵字參數後面跟了位置參數
#形參的相關操做閉包
#包括 1.位置參數 2.默認值參數,要先寫位置參數以後才能寫默認值參數 3.動態參數
包括:位置參數動態傳參 *args,關鍵字參數動態傳參**kwargs
無敵傳參方法:def func(*args,**kwargs):
#形參操做的例子:app
#1.位置參數,按照位置來進行賦值 # def chi(moning,after,night): # print(moning) # print(after) # print(night) # chi("餃子","米飯","麪條") #2.默認值參數 #例子:好比一個班上要錄入學生信息,有大部分都是男生,就能夠設置一個默認值是男 # def stu_inf(name,age,sex='男'): # print("錄入學生信息") # print(name,age,sex) # print("錄入完畢") # stu_inf("蔣小魚",18) # stu_inf("張衝",22) # stu_inf("沈擱",22,sex="女") #若是不想使用默認值也能夠本身設定 #注意點: #必須先聲明位置參數,才能聲明默認值參數,不然會有問題 #例子 # def stu_inf(name,sex='男',age): #很明顯這種寫法是錯誤的 #3.位置參數的動態傳參 # * 在這裏表示接收位置參數的動態傳參,接收到的是元組 # def chi(*foot): #參數名是food, * 表示動態傳參 # print(foot) # chi("米飯","麪條","餃子") #('米飯', '麪條', '餃子') # chi("饅頭") # chi() # def chi(name,*food,location="河北"): # print(location) # print(name+"要吃",food) # chi("張三","餃子","麪條") #要注意參數的書寫順序 #順序: 位置參數 -> 位置參數動態傳參 -> 默認值參數 #錯誤寫法 # def chi(name,location="河北",*food): # print(location) # print(name+"要吃",food) # chi("張三","餃子","麪條") #這樣寫的話餃子就成了默認值 # 餃子 # 張三要吃 ('麪條',) ''' #關鍵字的動態傳參 ''' # def chi(**food): # print(food) # # chi(good_food="大米",no_good_food="麪條",dirnk="水") #前面得是變量,若是寫數字或者字符串這種就會報錯,如:"大海" = "蝦" # def chi(*food2,**food): #這樣是無敵傳參 # print(food) # # chi(good_food="大米",no_good_food="麪條",dirnk="水") #提示: # 位置參數,*args(位置關鍵字動態傳參) 默認值參數 **kwargs 關鍵字動態傳參 # 以上參數能夠任意搭配使用,可是要注意順序問題,要否則會有問題
#參數的位置順序排列ide
位置參數->位置參數動態傳參*args->默認值參數->關鍵字參數動態傳參**kwargs
在函數裏面用三個單引號或三個雙引號引發來的就是函數的註釋
#例子:寫好註釋讓別人能看明白,能省去不少事情函數
# def chi(food,drink): # """ # 這裏是函數的註釋,先寫一下當前這個函數是幹什麼的,不如我這個函數就是一個吃 # :param food: 參數food是什麼意思 # :param drink: 參數drink是什麼意思 # :return: 返回的是什麼東西 # """ # print(food,drink) # return "good" # print(chi.__doc__) #document 文檔 # print(str.__doc__) #查看字符串的文檔註釋
#關於參數的聚合和打散spa
#形參:聚合 # def func(*food): # print(food) # lst = ["大麻花","餃子","麪條","土豆"] # func(lst) #這樣調用的話是一個列表在裏面的 # # 實參: 打散 # func(lst[0],lst[1],lst[2],lst[3]) #將上面的大三, 把list,tuple,set,str進行迭代打散 # func(*lst) #上面的打散寫不方便,寫*號更方便簡單 # #可是上面的打散都是一個一個的,那麼字典呢? #字典的打散方式 #聚合成關鍵字參數 # def func(**kwargs): # print(kwargs) # dic = {"name":"sir","age":"18"} # func(**dic) #打散成關鍵字參數
函數名也是一個變量,可是一個特殊的變量,與括號配合能夠執行函數的變量
#函數名的相關操做3d
1.函數名能夠賦值給其餘變量 2.函數名能夠做爲參數列表中的元素進行存儲,做容器類的元素 3.函數名能夠做爲參數傳遞給函數 4.函數名能夠做爲函數的返回值
#函數名相關操做例子:
# 一、函數名的內存地址 # def func(): # print("哈哈") # print(func) #由於尚未進行調用 #結果:<function func at 0x0000025A9344C1E0> # 2.函數名能夠賦值給其餘變量 # def func(): # print("哈哈") # # print(func) # a = func #把函數當成一個變量賦值給另外一個變量 # a() #函數調用func() #打印哈哈 # 3.函數名能夠看成容器類的元素 # def func1(): # print("哈哈") # # def func2(): # print("哈哈") # # def func3(): # print("哈哈") # # lst = [func1,func2,func3] # for i in lst: # i() # 4.函數名能夠做爲參數傳遞給函數 # def my(): # print("我是my") # # def proxy(fn): # fn() #執行傳遞過來的my # proxy(my) #過程:首先調用proxy函數,將my參數傳遞給proxy,而後變成proxy(my),而後調用my() #接着打印"我是my" #函數名能夠做爲參數進行傳遞(多層嵌套) # def func(): # print("我是func") # def func1(): # print("我是func1") # # def func2(fn): # print("我是func2") # fn() # func2(func1) #結果:我是func2,我是func1 #解釋:首先執行func2函數,而後有個實參傳遞給形參,打印我是func2,而後執行func1()函數打印我是func1 #例二: # def func(): # print("我是func") # def func1(): # print("我是func1") # # def func2(fn,gn): # print("我是func2") # fn() # gn() # print("hahaha") # func2(func1,func) # 我是func2 # 我是func1 # 我是func # hahaha #解釋:首先執行func2函數,有兩個實參傳遞給形參,打印我是func2,接着執行func1函數打印我是func1, #接着執行funch函數打印我是func,在打印hahaha # 5.函數名能夠做爲函數的返回值 # def func(): # print("我是func") # a = 10 # 變量 # def inner(): # print("我是inner") # return inner #得出inner,而後使用inner()調用 # print(func) # ret = func() # ret() # func()() #先運行func() 而後再返回值上加()
1.主要碰見()就是函數被調用了,若是沒有()就不是函數的調用
2.函數的執行順序
#函數嵌套例子
#例子: # def fun(): # print(111) # def fun1(): # print(222) # fun() # fun1() # print(111) #結果是222,111,111 #解釋:定義函數,而後最早調用的是fun1這個函數,因此先的打印fun1中的內容, #接着再調用fun()函數,再打印111,接着再打印111 #例二 # def fun1(): # print("蔣小雨") # def fun2(): # print("魯炎") # def fun3(): # print("張衝") # def fun4(): # print("龍大隊") # fun2() # fun4() # fun3() # def fun5(): # print("二哈") # fun1() # fun5() #二哈,蔣小雨,張衝,龍大隊,魯炎 #分析:首先調用fun5,打印二哈,接着調用fun1,打印蔣小雨,而後調用fun3的函數,打印張衝 #接着執行下面函數體代碼塊,調用fun4,打印龍大隊,接着調用fun2打印魯炎
把存放名字和值的關係的空間叫作命名空間
#命名空間分類
1.全局命名空間:在py文件中,函數外聲明的變量都屬於全局命名空間 2.局部命名空間:在函數中聲明的變量會放在局部命名空i教案 3.內置命名空間:存放python解釋器爲咱們提供的名字 如:list,tuple,str,int這些就是內置命名空間
#取值順序
1.局部命名空間 2.全局命名空間 3.內置命名空間 #取值順序例子: a = 10 #全局命名空間 def func(): a = 20 #局部命名空間 print(a) func() #20
定義:做用域就是做用的範圍,按照生效範圍分爲:全局做用域和局部做用域
全局做用域:包含內置命名空間和全局命名空間,在整個文件均可以使用
能夠經過globals()函數來查看全局做用域中的內容
局部做用域:在函數內部可使用
能夠經過locals()函數來查看局部做用域中的變量和函數信息
#例子:
#例子 # a = 10 # def func(): # a = 40 # b = 20 # def abc(): # print("哈哈") # print(a,b) #這裏使用的是局部做用域 # print(globals()) #打印全局做用域中的內容 # print(locals()) #打印局部做用域中的內容 # func()
#關鍵字global和nonlocal講解
global:更改全局變量中的值 理解:在局部中定義一個局部變量,而後加了global,就會將全局中定義的變量的值改爲局部的那個變量的值 #global的應用 #例子 # a = 10 # def func(): # global a # a += 10 # print(a) # func() #20 ,加了global就能夠改變外部的值了,若是不加是不能更改的 #例如:不加global更改全局參數的時候就會報錯 # a = 10 # def func1(): # a += 10 # print(a) # func1() #總結點:全局變量自己就是不安全的,不能隨意修改 nonlocal:尋找外層函數中離他最近的那個變量 #例子: # a = 10 # def func1(): # a = 20 # def func2(): # nonlocal a # a = 30 # print(a) # func2() # print(a) # func1() # print(a) #30,30,10 #nonlocal是更改離他最近的那個變量,因此,將上一個a=20,改成30 #因此打印是30,30,10,由於nonlocal將20改爲了30
定義:在內層函數中訪問外層函數的變量 閉包的做用: 1.能夠保護變量不受侵害 2.可讓一個變量常駐內存
#例子:
#做用例子: #一、保護變量不受侵害 #首先舉一個全局變量不安全的例子 # a = 10 # def outer(): # global a # a = 20 # print(a) # # def outer_2(): # global a # a = 30 # print(a) # # # outer() # outer_2() #得出結果是20,30 #解釋:首先調用outer()函數更改成20,而後再調用outer_2函數打印30 # 這樣就會出現哪一個先調用就執行那個,因此改來改去是很混亂的 # def outer(): # a = 10 #這個變量對外界是不開放的 # def func(): # nonlocal a #尋找外層函數中離他最近的那個進行修改 # a = 20 # print(a) # func() # outer() # # def outer_2(): #這個函數不能對a = 10進行修改 # pass #二、讓一個變量常駐內存 # def outer(): # a = 10 #常駐內存,爲了inner執行的時候有值,由於你不知何時調用 # def inner(): # print(a) # return inner # fn = outer() # print("大大大") # print("笑笑笑") # # fn() #至關於inner(),調用inner函數 #使用 _closure_ 查看函數是否是閉包 #例子:不是閉包的檢測 # def outer(): # def func(): # print("我不是閉包") # print(func.__closure__) #None # outer() #例二:是閉包 # def outer(): # a = 10 # def func(): # print(a) # print(func.__closure__) # outer() #(<cell at 0x000001B7B3E7D978: int object at 0x00007FF97124B470>,) #結論:若是打印的是None,不是閉包,若是不是None,就是閉包
#迭代器 # 能夠簡單理解爲:通用的去遍歷某個對象的方式 #有些數據類型是可迭代的,有些是不可迭代的,若是使用不可迭代的來進行循環就會報錯 #例子:使用不可迭代對象來進行循環就會報錯 # s = 123 # for i in s: # print(i) #這樣打印會報錯: TypeError: 'int' object is not iterable:數字不是一個可迭代對象 #那麼問題就來了,怎麼知道是否是一個可迭代對象呢? #能夠經過dir查看xx類型的數據能夠執行哪些方法 # print(dir(str)) #__iter__ iterable(可迭代) # print(dir(list)) #__iter__ # print(dir(int)) #若是沒有__iter__,說明不是可迭代對象,不是可迭代對象那麼相對應的就不能進行循環 #結論:全部的帶__iter__是可使用for循環的,是可迭代對象 #可迭代對象就可使用__iter__()來獲取到迭代器 #迭代器裏面有__next__() # s = "我喜歡看火藍刀鋒" # it = s.__iter__() #獲取迭代器 # print(dir(it)) #迭代器裏有__iter__ 還有__next__
#迭代器的特色
1.只能向前取,下一個下一個,不能往回 2.幾乎不佔用內存,能夠有效節省內存 3.for循環 4.惰性機制 #例子: 1.只能向前拿 #print(it.__next__()) #我 # print(it.__next__()) #喜 # print(it.__next__()) #歡 # print(it.__next__()) #看 # print(it.__next__()) #火 2.迭代器模擬for循環 # lst = ["蔣小雨","張衝","魯炎","龍大隊"] # for el in lst: #底層使用的是迭代器 # print(el)
#判斷數據是否可迭代
#例子: # lst = ["張衝","魯炎","蔣小雨"] #it = lst.__iter__() # print("__iter__" in dir(it)) #True # print("__next__" in dir(it)) #True # print(list(it)) #經過dir來判斷數據是否可迭代的,以及數據是不是迭代器 # # #官方方案 # from collections.abc import Iterable #可迭代對象 # from collections.abc import Iterator #迭代器 # # print(isinstance(lst,Iterable)) #True # print(isinstance(lst,Iterator)) #False lst列表自己不是迭代器
1.生成器的本質就是迭代器,和迭代器的特色同樣,取值方式和迭代器同樣(__next__(),send() 2.在python種有三種方式來獲生成器 1.經過生成器函數 2.經過各類推導式來實現生成器 3.經過數據的轉換也能夠獲取生成器
生成器函數
1.函數中若是由yield函數就是生成器函數 2.生成器函數在執行的時候,默認不會執行函數體,會返回生成器 3.yield:至關於return能夠返回數據,可是yield不會完全中斷函數,會分段執行函數 #例子:不執行函數體,拿到的是生成器 # def func(): # print('哈哈') # yield 1 # print('呵呵呵') # gen = func() #這樣子你就會發現不會執行你的函數,拿到的是生成器,若是是return的話就會執行函數了 # print(gen.__next__()) #這樣子就會執行函數,執行到下一個yield,就是說執行看到yield就結束
#生成器應用
#應用場景 # 好比你喜歡吃雞蛋,設想你去市場能夠一會兒就買一萬個,這樣也是能夠,可是有個問題就是雞蛋久了就會爛,存放是個問題,這樣就會很浪費,可是若是你買了個雞回來,就能夠解決掉存放空間問題,想何時吃就拿一個 #例子:一會兒買一萬個浪費 # def egg(): # lst = [] # for i in range(10000): # lst.append('雞蛋'+str(i)) # return lst # ll = egg() #一會兒買10000個就會很佔用內存 #例二:買只雞,生雞蛋,想吃一個就拿一個 # def egg(): # for i in range(10000): # yield '雞蛋'+str(i) # g = egg() #獲取生成器 # sir = g.__next__() # print(sir) #雞蛋0 # sir1 = g.__next__() # print(sir1) #雞蛋1 #這樣子就是想吃一個就拿一個 #這樣子也驗證了生成器的3個特色 # 1.惰性機制,拿一個纔給你取一個 # 2.省內存 # 3.只能向前拿
#send()方法
send()和__next__()是同樣的,能夠執行到下一個yield,能夠給上一個yield位置傳值 #send和__next__()區別: 1.send和next()都是讓生成器走下一次 2.send能夠給上一個yield的位置傳遞值,不能給最後一個yield發送值,在第一次執行生成器代碼的時候不能使用send()
#使用send給上一個yield傳值例子:
#例子:使用send給上一個yield傳值 def func(): print("我吃什麼啊") a = yield "玉米" #這裏的a和後面的yield是沒關聯的,會把傳進來的值交給print執行 print("a=",a) b = yield "餃子" print("b=",b) c = yield "包子" print("c=",c) yield "OVER" #最後收尾的必定是yield,否則會有報錯 g = func() #獲取生成器,記住有yield的是生成器函數,只會給你獲取到生成器,不會執行函數體 ret1 = g.__next__() #沒有上一個yield,因此不能使用send(),開頭必須__next__() print(ret1) ret2 = g.send("大餅") print(ret2) #a=大餅 ret3 = g.send("粥") print(ret3) #b=粥 ret4 = g.send("冰淇淋") print(ret4) #c=冰淇淋 #解析:執行時候首先我吃什麼啊,而後打印玉米,接着ret2使用send上一個yield傳值,因此就變成a=大餅,接着打印a=大餅 # 要注意變量和右邊的yield是兩段來的,互不相干,接着打印餃子,ret3使用send給上一個yield傳值,變成b=粥,接着繼續執行
#生成器可使用for循環來獲取內部的元素
#爲何生成器可使用for循環呢,由於生成器實質就是迭代器 #例子: def func(): print(111) yield 222 print(333) yield4444 print(555) yield 666 for i in func(): print(i)
1.推導式:就是使用一句話來生成 2.包括:列表推導式,字典推導式,集合推導式, 3.注意點:沒有元組推導式 4.3種推導式的語法: 1.列表推導式:[結果 for循環 條件判斷] 2.字典推導式:{k:v for循環 條件判斷} 3.集合推導式:{k for循環 條件判斷}
#3種推導式的應用
#1.列表推導式 語法: [結果 for循環 判斷語句] #例子:首先咱們先來一個打印一年級到12年級,咱們可能想到的是定義一個空列表,而後把元素追加到列表裏面 # lst = [] # for i in range(1,13): # lst.append("年級"+str(i)) # print(lst) #若是使用推導式的話,那麼就是使用一句話來生成一個列表 # lst = ["年級"+str(i) for i in range(1,13)] # print(lst) #和上面列表追加同樣的效果 #例二:使用推導式取1-100的奇數 # lst = [i for i in range(100) if i%2 == 1] # print(lst) #例三:尋找名字中帶有兩個e的人的名字 # names = [['Tom','tomi','findall','Wesley','Steven','Jon'],['Alice','Ana','Jennifer','Eva']] #邏輯:首先打開第一層列表,拿到下列表,而後再到小列表裏面拿元素,再進行統計判斷 #使用推導式寫 # lst = [name for line in names for name in line if name.count('e') ==2] # print(lst) #['Wesley', 'Steven', 'Jennifer'] #使用常規算法寫 # lst = [] # for line in names: # for name in line: # if name.count('e') == 2: # lst.append(name) # print(lst) #['Wesley', 'Steven', 'Jennifer'] #2.字典推導式 語法:{key:value for循環 條件判斷} #例子:將列表的元素轉換成字典,轉換形式:[11,22,33,44] => {0:11,1:22,2:33} # lst = [11,22,33,44] # dic = {i:lst[i] for i in range(len(lst))} # print(dic) #{0: 11, 1: 22, 2: 33, 3: 44} #例二:將字典的key和value進行調換 # 思路:首先先拿到key和value,而後在推導式的結果那裏掉不一樣位置就能夠了 # dic = {"zs":"趙四","ln":"劉能","zc":"張衝","ly":"魯炎"} # d = {v:k for k,v in dic.items()} # print(d) #{'趙四': 'zs', '劉能': 'ln', '張衝': 'zc', '魯炎': 'ly'} #3.集合推導式 #要記住集合的特色:去重,無序,元素必須式可哈希不可變的數據類型 #例1:使用集合推導式去重複 # s = {i for i in range(100)} # print(s) #例二:去重複 # lst= [1,2,3,4,2,1,3,4,6,7] # s = {el for el in lst} # print(s) #{1, 2, 3, 4, 6, 7}
1.生成器表達式能夠直接獲取到生成器對象,生成器對象能夠直接進行for循環,生成器具備惰性機制 2.生成器表達式語法: (結果 for 變量 in 可迭代對象 if 條件判斷)
#生成器表達式應用
#下面將演示生成器的最大點特,惰性機制,要拿纔給你拿一個,拿走了就沒有值了 # def func(): # print(111) # yield 222 # yield 333 # # a = func() #獲取到生成器 # a1 = (i for i in a) #生成器 # a2 = (i for i in a1) #生成器 # print(list(a)) #[222, 333] # print(list(a1)) #[] # print(list(a2)) #[] #分析:爲何前面的a有值,後面的都沒有值了? #解:由於a是源頭,他從源頭把數據給拿走了,因此後面再從前面拿的話就不會有值了,這就驗證了生成器的惰性機制,你拿一個纔給你一個,拿走了就沒有了 #那麼後面還能不能獲取到值? 答案是能夠的,能夠再作一個源頭,再拿數據 #例如:再定義一個a3獲取生成器,再進行調用,這樣子a2就有值了 # def func(): # print(111) # yield 222 # yield 333 # # a = func() #獲取到生成器 # a1 = (i for i in a) #生成器 # a3 = func() # a2 = (i for i in a3) #生成器 # print(list(a)) #[222, 333] # print(list(a1)) #[] # print(list(a2)) #[222, 333] #
#面試題
#題目:計算拿到的值是多少 #求和函數 # def add(a,b): # return a + b #生成器函數 # def test(): # for r_i in range(0,4): # yield r_i # # g = test() #獲取到生成器 # # for n in [2,10]: # g = (add(n,i) for i in g) #上的for能夠當作循環量詞 # for n in [2]: # g = (add(n,i) for i in g) # for n in [10]: # g = (add(n,i) for i in g) #由於是2還沒取值,因此是疊加進去,將g換成上面 # g = (add(n,i) for i in (add(n,i) for i in 0,1,2,3) # print(list(g)) #20,21,22,23 #分析:第一個函數是來求和得,第二個函數是生成器函數,沒有打印值,而後到for循環,能夠想象是2和10都執行了一次,可是由於生成器得惰性機制,而後執行2是沒有值,因此是不關2的事情,執行10得時候纔會執行,將10帶進去算 #最後的執行是這樣:g = (add(10,i) for i in (add(10,i) for i in 0,1,2,3),因此就成10+10,10+11,10+12,10+13 #提示:惰性機制,不到最後是不會拿值得 #下面接着演示列表有多個值,可是它只會看最後面的那個,前面的會相加 # def add(a,b): # return a + b #生成器函數 # def test(): # for r_i in range(0,4): # yield r_i # g = test() #獲取到生成器 # # for n in [1,3,7]: # g = (add(n,i) for i in g) #這個就是至關於疊加了3次 # g = (add(7,i) for i in (add(7,i) for i in (add(7,i) for i in 0,1,2,3) # print(list(g)) #21,22,23,24 #最後的運算是:(add(7,i) for i in (add(7,i) for i in (add(7,i) for i in 0,1,2,3) #將7帶進去運算,把最後那個帶進去算 #首先是0+7,1+7,2+7,3+7,接着7+7,7+8,7+9,7+10,而後7+14,7+15,7+16,7+17
#生成器表達和列表推導式的區別
1.生成器表達式比較省內存,列表推導式比較耗內存
2.獲得的值不同,列表推導式獲得的是一個列表,生成器表達式獲取的是生成器