Python之路11:函數(shù)之命名空間,閉包粒氧,生成器越除,迭代器

命名空間

名稱空間是存放變量名和賦值綁定關(guān)系的地方

名稱空間共 3 種:

  • locals: 是函數(shù)內(nèi)的名稱空間,包括局部變量和形參
  • globals: 全局變量外盯,函數(shù)定義所在模塊的名稱空間
  • builtins: 內(nèi)置模塊的名稱空間

不同變量的作用域不同是由這個變量所在的命名空間決定的
作用域范圍:

  • 全局變量:全局有效摘盆,全局存活
  • 局部變量:局部有效,局部存活

查看作用域的方法:globals(), locals()
作用域的查找規(guī)則:LEGB

閉包

閉包:返回的函數(shù)對象饱苟,不僅僅是一個函數(shù)對象孩擂,在該函數(shù)外還包裹了一層作用域,這使得箱熬,該函數(shù)無論在何處調(diào)用类垦,優(yōu)先使用自己外層的作用域

def func():
    name = 'jack'

  def inner():
        print('函數(shù)變量:', name)

    return inner

f = func()

f()
# 返回結(jié)果: 函數(shù)變量:jack

生成器

列表生成式

# 將列表中的每一個值都進(jìn)行自乘
# 可以通過列表生成式來完成
>>> a = list(range(10))
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a = [i*i for i in a]
>>> a
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# 以上就是通過簡單的列表生成式來實現(xiàn)的

生成器:
通過列表生成式,可以直接創(chuàng)建一個列表城须,但是受到內(nèi)存限制蚤认,列表的容量是有限的。
列表元素通過某種算法糕伐,再循環(huán)中不斷推算出后續(xù)的元素砰琢,這種一邊循環(huán)一邊計算的機(jī)制,稱為生成器:generator

# 要創(chuàng)建一個 generator 很簡單良瞧,就是將列表生成式中的 [] 改成 ()
>>> l = [i*i for i in range(10)]
>>> l
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x*x for x in range(10))
>>> g
<generator object <genexpr> at 0x7f77ffd6cdb0>

# 創(chuàng)建 l 和 g 的區(qū)別就是最外層的[] 和 (), l 是一個list陪汽,而 g 是 generator,可以直接打印獲取 list 所有元素褥蚯,但 generator 需要通過 next() 一個一個獲取
>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
25
>>> next(g)
36
>>> next(g)
49
>>> next(g)
64
>>> next(g)
81
>>> next(g)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
# 直到最后獲取不到拋出 StopIteration 錯誤
# 但用上面 next(g) 獲取太麻煩掩缓,可以通過 for 循環(huán)
>>> g = (x*x for x in range(10))
>>> for n in g:
...   print(n)
... 
0
1
4
9
16
25
36
49
64
81
# 而且這樣也不會報錯

著名的斐波拉契數(shù)列(Fibonacci),除第一個和第二個數(shù)外遵岩,任意一個數(shù)可由前兩個數(shù)相加所得
斐波拉契數(shù)列通過列表生成式無法寫出來你辣,但是可以通過函數(shù)打印出來

def fin(max):
    n, a, b = 0, 0, 1
    
    while n < max:
        print b
        a, b = b, a+b
        
        n += 1
    return 'done'

data = fin(5)
print(data)
# 執(zhí)行結(jié)果為
1
1
2
3
5

# 上面 fin 函數(shù)實際上是定義了斐波拉契數(shù)列的推算規(guī)則,可以從第一個元素推算出后續(xù)任意的元素
# 要講上面函數(shù)變成 generator尘执,只需要把 print b 改為 yield b
def fin(max):
    n, a, b = 0, 0, 1
    
    while n < max:
        # print b
        yield b
        a, b = b, a+b
        
        n += 1
    return 'done'

data = fin(5)
print(data)
# 執(zhí)行結(jié)果:<generator object fib at 0x00000232F05DEF68>

# 這是函數(shù)中定義 generator 的一種方法舍哄,如果一個函數(shù)內(nèi)包含 yield 字段,那么這個函數(shù)就不再是一個普通函數(shù)誊锭,而是一個 generator

# generator執(zhí)行過程和函數(shù)是不同的表悬,函數(shù)執(zhí)行是順序執(zhí)行,需要 return語句或者最后一行語句返回丧靡,而 generator函數(shù)蟆沫,則是每次調(diào)用 next() 的時候執(zhí)行籽暇,遇到 yield語句返回,如沒有next()饭庞,函數(shù)執(zhí)行到 yield 是就停止不再繼續(xù)執(zhí)行了戒悠,再次被 next() 調(diào)用時從上次返回的 yield 語句繼續(xù)執(zhí)行下,在次遇到 yield 語句返回并停止

迭代器

  • 可迭代對象
    可以直接作用于 for 循環(huán)的對象稱為可迭代對象:Iterable
    可直接作用于 for 循環(huán)的數(shù)據(jù)類型有以下幾類:
    一類是集合數(shù)據(jù)類型:list ,tuple, dict, set, str 等
    一類是 generator舟山,包括生成器和帶 yield 的generator functions
    可以使用 isinstance() 判斷一個對象是否是 Iterable(可迭代)對象
>>> from collections import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance((), Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance(123, Iterable)  # 整數(shù)就不是可迭代對象
False

而生成器不但可以作用于 for 循環(huán)绸狐,還可以被 next() 函數(shù)不斷的調(diào)用并返回下一個值,直到最后拋出 Stoplteration 錯誤并返回

  • 迭代器
    可以被 next() 函數(shù)調(diào)用并不斷返回下一個值的對象稱為 迭代器:Iterator
    可以用 isinstance()判斷一個對象是否是 Iterator(迭代)對象:
>>> isinstance((i for i in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance('abc', Iterator)
False

# 生成器都是 Iterator(迭代器)對象累盗,但 list寒矿,str, dict 雖然是 Iterable(可迭代對象), 但不是 Iterator(迭代器)

可以通過 iter() 函數(shù)把 Iterable 變成 Iterator

>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True

Python 中 Iterator 對象表示的是一個數(shù)據(jù)流,Iterator 對象可以被 next() 函數(shù)調(diào)用并不斷返回下一個數(shù)據(jù)若债,直到?jīng)]有數(shù)據(jù)拋出 StopIteration 錯誤符相,可以把這個數(shù)據(jù)流看做是一個有序序列,但我們卻不能提前知道序列的長度蠢琳,只能不斷通過next()函數(shù)實現(xiàn)按需計算下一個數(shù)據(jù)主巍,所以Iterator的計算是惰性的,只有在需要返回下一個數(shù)據(jù)時它才會計算挪凑。

  • 總結(jié)

凡是可作用于 for 循環(huán)的對象都是 Iterable 類型
凡是可作用于 next() 函數(shù)的對象都是 Iterator 類型孕索,它們表示一個惰性計算的序列
集合類型如 list,dict躏碳,str等都是 Iterable搞旭,但不是 Iterator, 但是可以通過 iter() 函數(shù)獲得一個 Iterator 對象
python3 的 for 循環(huán)本質(zhì)上就是通過不斷調(diào)用 next() 函數(shù)實現(xiàn)的

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市菇绵,隨后出現(xiàn)的幾起案子肄渗,更是在濱河造成了極大的恐慌,老刑警劉巖咬最,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翎嫡,死亡現(xiàn)場離奇詭異,居然都是意外死亡永乌,警方通過查閱死者的電腦和手機(jī)惑申,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來翅雏,“玉大人圈驼,你說我怎么就攤上這事⊥福” “怎么了绩脆?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我靴迫,道長惕味,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任玉锌,我火速辦了婚禮名挥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘芬沉。我一直安慰自己,他們只是感情好阁猜,可當(dāng)我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布丸逸。 她就那樣靜靜地躺著,像睡著了一般剃袍。 火紅的嫁衣襯著肌膚如雪黄刚。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天民效,我揣著相機(jī)與錄音憔维,去河邊找鬼。 笑死畏邢,一個胖子當(dāng)著我的面吹牛业扒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播舒萎,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼程储,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了臂寝?” 一聲冷哼從身側(cè)響起章鲤,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎咆贬,沒想到半個月后败徊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡掏缎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年皱蹦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片眷蜈。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡根欧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出端蛆,到底是詐尸還是另有隱情凤粗,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站柔袁,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏异逐。R本人自食惡果不足惜捶索,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望灰瞻。 院中可真熱鬧腥例,春花似錦、人聲如沸酝润。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽要销。三九已至构回,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間疏咐,已是汗流浹背纤掸。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留浑塞,地道東北人借跪。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像酌壕,于是被迫代替她去往敵國和親垦梆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容