1. 程式人生 > >python學習 day011打卡 迭代器

python學習 day011打卡 迭代器

本節的主要內容:

1.函式名的使用以及第一類物件

2.閉包

3.迭代器

 

一.函式名的運用.

函式名是一個變數,但它是一個特殊的變數,與括號配合可以執行函式的變數.

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("呵呵") 

def func4():    
    print("呵呵") 

lst = [func1, func2, func3] 
for i in lst:   
    i()

 4.函式名可以當做函式的引數

def chi(fn): # fn 代理了func1和func2
    print("開掛")
    fn()
    
print(fn.__name__) print("洗包") def play_dnf(): print("瘋狂的刷") def func1(): print("我是func1") def func2(): print("我是func2") def he(): print("我要喝酒") chi(he)

 

代理模式

裝飾器的雛形

把函式名當成變數來使用

5.函式名可以作為函式的返回值

def outer():
    def inner():
        print("哈哈")
    return inner
outer()()

 

二.閉包

閉包就是內層函式,對外層函式(非全域性)的變數的引用,叫閉包

def func1():    
    name = "alex"    
    def func2():        
        print(name)     # 閉包    
    func2() 
func1() 
結果: 
alex    

 我們可以使用__closure__來檢測函式是否是閉包.使用函式名.__closure__返回cell就是閉包.返回None就不是閉包

def outer():
    # a = 10
    def inner():
        print("哈哈")
    print(inner.__closure__) # (<cell at 0x000001C079677588: int object at 0x0000000054776D30>,)
    return inner

 

問題:如何在函式外邊呼叫內部函式呢?

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()()()                    

 有它我們可以引出閉包的好處.由於我們在外界可以訪問內部函式.那這個時候內部函式訪問的時間和時機就不一定了,因為在外部,我

可以選擇在任意的時間去訪問內部函式.這個時候.想一想.我們之前說過,如果一個人函式執行完畢.則這個函式中的變數以及區域性名稱空間

中的內容都將會被銷燬.在閉包中,如果變數被銷燬了.那內部函式將不能正常執行.所以,python規定,如果你在內部函式中訪問了外層函式

的變數.name這個變數將不會消亡.將會常駐在記憶體中.也就是說,使用閉包,可以保證外層函式中的變數在記憶體中常駐.這樣做有什麼好處呢?

非常大的好處.我們來看一個關於爬蟲的程式碼:

from urllib.request import urlopen # 開啟一個連線用的模組
# 外層函式
def but():
    # 開啟連線. 讀取原始碼
    content = urlopen("http://www.cctv.com/").read() # 永久駐留在記憶體
    # 內層函式
    def get_content():
            # 返回content
        return content
    return get_content # 內層函式

fn = but() # 這裡會很慢. 需要網路請求
print(fn()) # 不會再進行網路請求了
print(fn())

 綜上,閉包的作用就是讓一個變數能夠常駐記憶體,供後面的程式使用

閉包的作用:

1.保護我們的變數不受侵害

2.可以讓一個變數常駐記憶體

三.迭代器

我們之前一直在用可迭代物件進行迭代操作,那麼到底什麼是可迭代物件?

我們熟悉的可迭代物件有:

str,list,tuple,dict,set.那為什麼我們可以稱他們為可迭代物件呢?因為他們都遵循了可迭代協議.

我們可以通過dir函式來檢視類中定義好的所有辦法.

print(dir(str)) # 檢視str能夠執行的操作. 內部的方法

在列印結果中,尋找__iter__如果能找到,那麼這個類的物件就是一個可迭代物件

我們發現這幾個可以進行for迴圈的東西都有__iter__函式,包括range也有.可以自己試一下.

這是檢視一個物件是否是可迭代物件的第一種辦法.我們還可以通過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 

# collections 關於集合類的相關操作
# Iterable : 可迭代的
# Iterator : 迭代器

綜上.我們可以確定,如果物件中有__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 Ture :
    try :
        i = lst_iter.__next__()
        print(i)
    except StopIteration :
        break

 

 

總結:

iterable:可迭代函式

物件.內部包含__iter__()

Iterator:迭代器.內部包含__iter__()同時包含__next__().

迭代器的特點:

1.節省記憶體.

2.惰性機制.

3.不能反覆,只能向下執行.

 我們可以把要迭代的內容當成子彈.然後呢.獲取到迭代器__iter__().就把子彈都裝在單價中.然後發射就是__next__()把每一個子彈(元素)打出來.

也就是說,for迴圈的時候.一開始的時候是__iter__()來獲取迭代器.很後面每次獲取元素都是通過該__next__()來完成的.當程式遇到StopIteration將結束迴圈.