day 10
四,函數名的本質。
函數名本質上就是函數的內存地址。
1.可以被引用
def func():print('in func')f = func print(f)?
2.可以被當作容器類型的元素
def f1():print('f1)def f2():print('f2')def f3():print('f3')l = [f1, f2, f3]d = {'f1':f1, 'f2': f2, 'f3': f3} # 調用 l[0]() d['f2']()?
3.可以當作函數的參數和返回值
def f1():print('f1')def func2(argv):argv()return argvf = func1(f1) f()?
可以作為第一類對象使用:第一類對象(first-class object)指 1.可在運行期創建 2.可用作函數參數或返回值 3.可存入變量的實體。
*不明白?那就記住一句話,就當普通變量用
?五,閉包
def func():name = '太白金星'def inner():print(name)?
閉包函數:
內部函數包含對外部作用域而非全劇作用域變量的引用,該內部函數稱為閉包函數
#函數內部定義的函數稱為內部函數
?
由于有了作用域的關系,我們就不能拿到函數內部的變量和函數了。如果我們就是想拿怎么辦呢?返回呀!
我們都知道函數內的變量我們要想在函數外部用,可以直接返回這個變量,那么如果我們想在函數外部調用函數內部的函數呢?
是不是直接就把這個函數的名字返回就好了?
這才是閉包函數最常用的用法
def func():name = 'eva'def inner():print(name)return innerf = func() f()判斷閉包函數的方法__closure__#輸出的__closure__有cell元素 :是閉包函數 def func():name = 'eva'def inner():print(name)print(inner.__closure__)return innerf = func() f()#輸出的__closure__為None :不是閉包函數 name = 'egon' def func2():def inner():print(name)print(inner.__closure__)return innerf2 = func2() f2()?
閉包的嵌套 def wrapper():money = 1000def func():name = 'eva'def inner():print(name,money)return innerreturn funcf = wrapper() i = f() i() 閉包的網絡應用 from urllib.request import urlopen def but():content = urlopen("http://www.cnblogs.com/jin-xin/articles/8259929.html").read()def get_content():return contentreturn get_content fn = but() content = fn() # 獲取內容 print(content.decode('utf-8')) #中文顯示 content2 = fn() # 重新獲取內容 print(content2.decode('utf-8'))一,迭代器
1.1什么是可迭代對象?
字符串、列表、元組、字典、集合都可以被for循環,說明他們都是可迭代的。
我們怎么來證明這一點呢?
from collections import Iterablel = [1,2,3,4] t = (1,2,3,4) d = {1:2,3:4} s = {1,2,3,4} print(isinstance(l,Iterable)) print(isinstance(t,Iterable)) print(isinstance(d,Iterable)) print(isinstance(s,Iterable))?
1.2可迭代協議
我們現在是從結果分析原因,能被for循環的就是“可迭代的”,但是如果正著想,for怎么知道誰是可迭代的呢?
假如我們自己寫了一個數據類型,希望這個數據類型里的東西也可以使用for被一個一個的取出來,那我們就必須滿足for的要求。這個要求就叫做“協議”。
可以被迭代要滿足的要求就叫做可迭代協議。可迭代協議的定義非常簡單,就是內部實現了__iter__方法。
接下來我們就來驗證一下:
print(dir([1,2])) print(dir((2,3))) print(dir({1:2})) print(dir({1,2}))?
總結一下我們現在所知道的:可以被for循環的都是可迭代的,要想可迭代,內部必須有一個__iter__方法。
接著分析,__iter__方法做了什么事情呢?
可迭代的:內部必須含有一個__iter__方法。
1.3迭代器
什么叫做迭代器?迭代器英文意思是iterator。
l = [1,2,3,4] l_iter = l.__iter__() # 將可迭代的轉化成迭代器 item = l_iter.__next__() print(item) item = l_iter.__next__() print(item) item = l_iter.__next__() print(item) item = l_iter.__next__() print(item) item = l_iter.__next__() print(item)?
迭代器遵循迭代器協議:必須擁有__iter__方法和__next__方法。
for循環,能遍歷一個可迭代對象,他的內部到底進行了什么?
- 將可迭代對象轉化成迭代器。(可迭代對象.__iter__())
- 內部使用__next__方法,一個一個取值。
- 加了異常處理功能,取值到底后自動停止。
用while循環模擬for循環:
l = [1,2,3,4] l_iter = l.__iter__() while True:try:item = l_iter.__next__()print(item)except StopIteration:break1.4為什么要有for循環?
基于上面講的列表這一大堆遍歷方式,聰明的你立馬看除了端倪,于是你不知死活大聲喊道,你這不逗我玩呢么,有了下標的訪問方式,我可以這樣遍歷一個列表啊
=[1,2,3]index=0 while index < len(l):print(l[index])index+=1#要毛線for循環,要毛線可迭代,要毛線迭代器沒錯,序列類型字符串,列表,元組都有下標,你用上述的方式訪問,perfect!但是你可曾想過非序列類型像字典,集合,文件對象的感受,所以嘛,年輕人,for循環就是基于迭代器協議提供了一個統一的可以遍歷所有對象的方法,即在遍歷之前,先調用對象的__iter__方法將其轉換成一個迭代器,然后使用迭代器協議去實現循環訪問,這樣所有的對象就都可以通過for循環來遍歷了,而且你看到的效果也確實如此,這就是無所不能的for循環,最重要的一點,轉化成迭代器,在循環時,同一時刻在內存中只出現一條數據,極大限度的節省了內存~
轉載于:https://www.cnblogs.com/yang950718/p/10268199.html
總結
- 上一篇: 安捷伦(Agilent)示波器使用简介
- 下一篇: 兄弟俩今年的年龄和是35岁,当哥哥像弟弟