一 : 函數名的運用 1.函數名的記憶體地址 2.函數名可以賦值給其他變數 3.函數名可以當做容器類的元素 4.函數名可以當做函數的參數 5.函數名可以作為函數的返回值 二 : 閉包 閉包就是內層函數,對外層函數(非全局)的變數的引用 我們可以使用__closure__來檢測函數是否是閉包,返回cel ...
一 : 函數名的運用
1.函數名的記憶體地址
def func(): print("呵呵") print(func) 結果: <function func at 0x1101e4ea0>
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 func(): print("吃了了麽") def func2(fn): print("我是func2") fn() # 執⾏行行傳遞過來的fn print("我是func2") func2(func) # 把函數func當成參數傳遞給func2的參數fn.
5.函數名可以作為函數的返回值
def func_1(): print("這裡是函數1") def func_2(): print("這裡是函數2") print("這裡是函數1") return func_2 fn = func_1() # 執行函數1. 函數1返回的是函數2, 這時fn指向的就是上面函數2 fn() # 執行上面返回的函數
二 : 閉包
閉包就是內層函數,對外層函數(非全局)的變數的引用
def func1(): name = "alex" def func2(): print(name) # 閉包 func2() func1() 結果: alex
我們可以使用__closure__來檢測函數是否是閉包,返回cell就是閉包,返回None就不是.
def func1(): name = "alex" def func2(): print(name) # 閉包 func2() print(func2.__closure__) # (<cell at 0x10c2e20a8: str object at 0x10c3fc650>,) func1()
在函數外邊調用內部函數的方法:
def outer(): name = "alex" # 內部函數 def inner(): print(name) return inner fn = outer() # 訪問外部函數, 獲取到內部函數的函數地址 fn() # 訪問內部函數
同樣的,當有多層嵌套的時候:
def func1(): def func2(): def func3(): print("嘿嘿") return func3 return func2 func1()()()
使用閉包的好處 : 可以保證外層函數中的變數在記憶體中常駐,供後邊的程式使用
三 : 迭代器
首先明確一個概念--可迭代對象,即str,list,tuple,dict,set,他們之所以是可迭代對象,是因為遵循了可迭代協議,通過dir()函數查看類中定義的所有方法,如果其中存在__iter__,那麼這個類的對象就是可迭代對象.Iterable意為可迭代對象,Iterator意為迭代器,這是兩個概念.
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
可以看到迭代器l執行了__iter__()方法之後獲得了一個迭代器l_iter,可迭代對象不一定是迭代器,迭代器卻一定是可迭代對象,那麼迭代器是如何運行的呢,再看一段代碼:
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
可以知道迭代器每次執行__next__()函數會返回可迭代對象的一個元素,當迭代完成再執行__next__()會報錯StopIteration,知道迭代器的原理之後,我們回頭再看for迴圈的原理:
for i in [1,2,3]: print(i) 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. 不能反覆, 只能向下執行.