一,閉包python
什麼是閉包呢?閉包就是內層函數,對外層函數(非外層)的變量的引用,叫作閉包git
1 def mz(): 2 name = 'YJ' 3 def xue(): 4 print(name) #閉包 5 xue() 6 mz() 7 結果:YJ
咱們可使用__closure__來檢查函數是否爲閉包,使用函數名__closure__返回內存地址就是閉包,返回None就不是閉包api
1 def mz(): 2 name = 'YJ' 3 def xue(): 4 print(name) #閉包 5 xue() 6 print(xue.__closure__ ) #(<cell at 0x0000017198AB48B8: str object at 0x00000171989C76C0>,) 7 mz()
問題那麼來了,如何在函數外邊調用內部函數呢?閉包
1 def mz(): 2 name = 'YJ' 3 #內部函數 4 def xue(): 5 print(name) 6 return xue 7 mingzhi = mz() #訪問外部函數,獲取到內部函數的函數地址 8 mingzhi() 訪問內部函數
那麼若是多層嵌套呢?很簡單,只須要一層一層的往外層返回就好了ssh
1 def xue(): 2 def xue1(): 3 def xue2(): 4 print('堅持') 5 return xue2 6 return xue1 7 xue()()() 8 結果:堅持
由它咱們能夠引出閉包的好處. 因爲咱們在外界能夠訪問內部函數. 那這個時候內部函數訪問的時間和時機就不必定了, 由於在外部, 我能夠選擇在任意的時間去訪問內部函數,
這個時候. 想想. 咱們以前說過, 若是一個函數執行完畢. 則這個函數中的變量以及局部命名空間中的內容都將會被銷燬. 在閉包中. 若是變量被銷燬了,
那內部函數將不能正常執行,因此, python規定若是你在內部函數中訪問了外層函數中的變量,那麼這個變量將不會消亡將會常駐在內存中,也就是說
使用閉包, 能夠保證外層函數中的變量在內存中常駐,供後面的程序使用
閉包的好處:
1. 保護你的變量不受外界影響
2. 可讓變量常駐內存
寫法:
def outer():
a = 10
def inner():
print(a)
return inneride
三,迭代器
迭代器
使用dir來查看該數據包含了那些方法
用來遍歷列表,字符串,元祖....可迭代對象
可迭代對象: Iterable, 裏面有__iter__()能夠獲取迭代器, 沒有__next__()
迭代器: Iterator, 裏面有__iter__()能夠獲取迭代器, 還有__next__()函數
迭代器特色:
1. 只能向前.
2. 惰性機制.
3. 省內存(生成器),只能向下執行spa
for循環的內部機制.
1. 首先獲取到迭代器.
2. 使用while循環獲取數據
3. it.__next__()來獲取數據
4. 處理異常 try:xxx except StopIteration:翻譯
it = xx.__iter__()
while 1:
try:
data = it.__next__()
xxxxxx
except StopIteration:
breakcode
咱們以前一直在用可迭代對象進行迭代操做,那麼到底什麼是可迭代對象目前咱們所熟知的可迭代對象都有哪些?
目前所學的可迭代對象有:str, list, tuple, dict, set. 那爲什麼咱們能夠稱他們爲可迭代對象呢?由於他們都遵循了可迭代協議,
什麼是可迭代協議,首先咱們先看一段錯誤代碼:
1 #可迭代的 2 a = 'Python' 3 for i in a: 4 print(i) 5 #不可迭代的 6 b = 123 7 for el in b: 8 print(el)
注意看報錯的信息中有這樣的一句話TypeError: 'int' object is not iterable翻譯過來就是整數數據類型對象是不可迭代的iterable表示可迭代的,那麼如何驗證你的數據類型是否可迭代的呢?咱們能夠經過dic函數來查看類中定義好的全部方法
1 a = 'Python' 2 print(dir(a)) #能夠打印對象中的⽅方法和函數 3 print(dir(str)) # 也能夠打印類中聲明的⽅方法和函數
在打印結果中. 尋找__iter__ 若是能找到,那麼這個類的對象就是一個可迭代對象了
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
字符串中能夠找到__iter__這些也是能夠找到的list, tuple, dict, set
能夠進行for循環的東西都有__iter__函數,包括range也有,能夠本身試一下
那麼咱們認爲這個對象遵照了可迭代協議就能夠獲取到相應的迭代器,這里的__iter__是幫助咱們獲取到對象的迭代器. 咱們使用迭代器中的__next__()來獲取到一個迭代器中的元素. 那麼咱們以前講的for的工做原理究竟是什麼? 看以下代碼:
for循環機制
1 for i in [1,2,3]:
2 print(i)
2019年11月9日