day 10 函式名的運用,閉包,迭代器
阿新 • • 發佈:2019-01-02
函式名的本質
函式名本質上就是函式的記憶體地址
函式名的五種運用:
1、函式名是一個變數
def func(): print(666) print(func) # 函式的記憶體地址 <function func at 0x000002B6D2559AE8>
2、函式名可以當做變數賦值
def func(): print(666) f1 = func f2 = f1 f2()
3、函式名可以當做容器類資料型別的元素
def func1(): print(111) def func2(): print(222) def func3(): print(333) l1 = [func1, func2 ,func3] for i in l1: i()
4、函式名可以當做函式的引數
def func(x): # x == func1 x() print('in func') def func1(): print('in func1') func(func1)
5、函式名可以當做函式的返回值
def func(x): # x ---> func1 return x # func1 def func1(): print('in func1') ret = func(func1) # ret = func1 ret() # func1() func(func1)() # x() == func1()
滿足3,4,5 函式名也稱為第一類物件
閉包:
什麼是閉包:
def func(): name = 666 print(111) def func1(): print(name) # 這就是閉包, 內層函式對外層函式(非全域性)變數的引用 func1() func()
1,內層函式對外層函式(非全域性)變數的引用。
2,閉包只存在於內層函式中。
3,函式都要逐層返回,最終返回給最外層函式。
def func(): name = 'alex' def inner(): print(name) return inner f = func() # f = inner f()
閉包的判斷
f.__closure__[0].cell_contents 閉包引用的外部變數
def func(): name = 'alex' age = 19 def inner(): print(name) print(age) return inner f = func() # 定義f,因為f是閉包 # 獲取閉包引用的外層變數,如果不是閉包則報錯 print(f.__closure__[0].cell_contents) #固定用法 19 print(f.__closure__[1].cell_contents) # alex
閉包有什麼用?
閉包:直譯器執行程式時,如果遇到函式,隨著函式的結束而關閉臨時名稱空間,但是!!!如果遇到閉包,有一個機制:那麼閉包的空間不會隨著函式的結束而關閉。
def wrapper(step): num =1 def inner(): nonlocal num num += step print(num) # 輸出 4 7 10 13 16 return inner f = wrapper(3) j = 0 while j < 5: f() j += 1
閉包就是在記憶體中開一個空間,常貯存一些內容,以便後續程式呼叫
閉包的應用:
1、裝飾器
2、爬蟲
迭代物件:
iterable: 可迭代物件
內部含有__iter__方法的就是可迭代物件,遵循可迭代協議
s1 = 'barry' l1 = [1, 2, 3] print('__iter__' in dir(s1)) # True 是可迭代物件
可迭代物件不能直接取值(含索引的迭代物件除外) ,需要轉換成迭代器才能取值
迭代器
迭代器:內部含有'__iter__'並且含有'__next__'方法的就是迭代器,遵循迭代器協議。
可迭代物件轉換成迭代器:
可迭代物件.__iter__()
obj = iter(可迭代物件)
判斷一個一個物件是否是迭代器(含iter,next)或迭代物件
方法一: 看__iter__ , __next__ 在不在dir() 裡面
s1 = 'abcdefg' obj = iter(s1) # 將s1轉換成迭代器 print('__iter__' in dir(s1)) # True print('__iter__' in dir(obj)) # True print('__iter__' in dir(s1) and '__next__' in dir(s1)) # False print('__iter__' in dir(obj) and '__next__' in dir(obj)) # True
方法二: isinstance(obj, Iterable/Iterator)
s1 = 'abcdefg' obj = iter(s1) # 將s1轉換成迭代器 from collections import Iterable # 迭代物件 from collections import Iterator # 迭代器 print(isinstance(obj,Iterator)) # 判斷obj是否為迭代器 True print(isinstance(obj,Iterable)) # 判斷obj是否為可迭代物件 True print(isinstance(s1,Iterator)) # 判斷obj是否為迭代器 False print(isinstance(s1,Iterable)) # 判斷obj是否為可迭代物件 True
迭代器取值
s2 = [1, 2, 3] obj = iter(s2) print(obj.__next__()) # 方法一 print(next(obj)) # 方法二
type() isinstance()區別?
# type()只是判斷該物件的資料型別
# isinstance()不僅可以判斷該物件的資料型別,而且可以判斷其他很多
迭代器的作用:
1、節省記憶體
2、惰性機制 (netx())一下,出一個值
3、一條路走到黑,不走回頭路
While迴圈模擬for迴圈機制
l1 = [i for i in range(10)] obj = iter(l1) while 1: try: # 試一試,如果報錯就執行下面的命令 print(next(obj)) except StopIteration: break