函數名、閉包 、迭代器

一、 函數名的使用注意.

函數名是⼀個變量, 但它是⼀個特殊的變量, 與括號配合可以執⾏函數的變量。
1. 函數名可以賦值給其他變量
2. 函數名可以當做容器類的元素
3. 函數名可以當做函數的參數
4. 函數名可以作爲函數的返回值

二、 閉包

什麼是閉包? 閉包就是內層函數對外層函數(非全局)的變量的引⽤。示例如下:

def func1():
     name = "倚窗頻頻醉夕陽"
     def func2():
        print(name) # 閉包
     func2()
func1()

我們可以使⽤__closure__來檢測函數是否是閉包. 使⽤函數名.__closure__返回cell就是
閉包,返回None就不是閉包,示例:

def func1():
     name = "倚窗頻頻醉夕陽"
     def func2():
        print(name) # 閉包
     func2()
     print(func2.__closure__)
func1()

結果:
在這裏插入圖片描述
在函數外邊調用內部函數:

def outer():
     name = "昔時織就相思網"
     # 內部函數
     def inner():
         print(name)
     return inner
fn = outer() # 訪問外部函數, 獲取到內部函數inner的函數地址
fn() # 訪問內部函數

結果:
在這裏插入圖片描述
如果多層嵌套只需要⼀層⼀層的往外層返回就可以了,如:

def func1():
     def func2():
         def func3():
             print("萬里雲天萬里霜")
         return func3
     return func2
func1()()()

結果:
在這裏插入圖片描述
我們之前說過, 如果⼀個函數執行完畢. 則這個函數中的變量以及局部命名空間中的內容都將會被銷燬. 在閉包中, 如果變量被銷燬了,那內部函數將不能正常執⾏。所 以python規定, 如果你在內部函數中訪問了外層函數中的變量,那麼這個變量將不會消亡,將會常駐在內存中. 也就是說,使⽤閉包, 可以保證外層函數中的變量在內存中常駐。 這樣做有什麼好處呢? 非常⼤的好處,比如說你做一個爬蟲程序需要爬取某網站的一部分內容,將它傳給一個局部變量,在全局訪問時就不用再執⾏⾮常耗時的網絡連接操作了。總之,一句話: 閉包的作⽤就是讓⼀個變量能夠常駐內存,供後⾯的程序使用。

三. 迭代器

我們之前⼀直在⽤可迭代對象進⾏迭代操作,那麼到底什麼是可迭代對象. ⾸先我們先回顧⼀下⽬前我們所熟知的可迭代對象有哪些:str, list, tuple, dict, set.
那爲什麼我們可以稱他們爲可迭代對象呢? 因爲他們都遵循了可迭代協議. 什麼是可迭代協議. ⾸先我們先看以下錯誤代碼:

for i in 123:
	 print(i)

注意看報錯信息中有這樣⼀句話. ‘int’ object is not iterable . 翻譯過來就是整數類型對象
是不可迭代的。iterable表⽰可迭代的,表⽰可迭代協議. 那麼如何進⾏驗證你的數據類型是否符合可迭代協議?
我們可以通過dir函數來查看類中定義好的所有⽅法.如:

print(dir(str)) # 打印類中聲明的⽅法和函數

結果:
在這裏插入圖片描述

查看一個對象是否是可迭代對象方法

1.用dir()函數在打印結果中. 尋找__iter__ ,如果能找到,那麼這個類的對象就是⼀個可迭代對象.
2.通過isinstence()函數來查看⼀個對象是什麼類型的如:

l = [1,2,3]
l_iter = l.__iter__()
from collections import Iterable
from collections import Iterator
print(isinstance(l,Iterable)) #True 表明是可迭代的,遵守可迭代協議
print(isinstance(l,Iterator)) #False
print(isinstance(l_iter,Iterator)) #True   表明是迭代器
print(isinstance(l_iter,Iterable)) #True

綜上. 我們可以確定. 如果對象中有__iter__函數. 那麼我們認爲這個對象遵守了可迭代協議,就可以獲取到相應的迭代器. 這⾥的__iter__是幫助我們獲取到對象的迭代器. 我們使⽤迭代器中的__next__()來獲取到⼀個迭代器中的元素. 那麼我們之前講的for的⼯作原理到底是什麼, 繼續看代碼:

s = "一簾幽夢曉生涼"
c = s.__iter__() # 獲取迭代器
print(c.__next__()) # 使⽤迭代器進⾏迭代. 獲取⼀個元素 一
print(c.__next__()) # 簾
print(c.__next__()) # 幽
print(c.__next__()) # 夢
print(c.__next__()) # 曉
print(c.__next__()) # 生
print(c.__next__()) # 涼
print(c.__next__()) # StopIteration

結果:
在這裏插入圖片描述
for循環的機制:

for i in [1,2,3]:
 print(i)

使⽤while循環+迭代器來模擬for循環:

lst = [1,2,3]
lst_iter = lst.__iter__()
while True:
     try:
         i = lst_iter.__next__()
         print(i)
     except StopIteration:
         break

總結:

Iterable: 可迭代對象. 內部包含__iter__()函數
Iterator: 迭代器. 內部包含__iter__() 同時包含__next__().
迭代器的特點:

  1. 節省內存.
  2. 惰性機制
  3. 不能反覆, 只能向下執⾏.
    我們可以把要迭代的內容當成⼦彈,然後獲取到迭代器__iter__(), 就把⼦彈都裝在彈夾中,然後發射就是__next__()把每⼀個⼦彈(元素)打出來。即 for循環的時候,⼀開始時是__iter__()來獲取迭代器,後⾯每次獲取元素都是通過__next__()來完成的,當程序遇到StopIteration將結束循環。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章