1. 程式人生 > >Python函數篇(4)之叠代器與生成器

Python函數篇(4)之叠代器與生成器

依賴 true windows 想要 bject 多個 介紹 中文 linux系統中

1.文件操作的“b模式”(補充)

  在上一篇文章中,我在最後一部分寫了文件處理的一些方法,但是覺得還是有必要再提一下如下的內容:

  像rb、wb、ab這種模式,是以字節的形式操作,需要註意以下幾個問題:

  1)文件不能保存在內存中,只能保存在硬盤中,以二進制的形式,Python只能將字符串寫入文本文件,要將數值數據存儲到文本文件中,必須先使用函數str()將其轉化為字符串格式。

  2)在以rb .rw等編碼打開文件的時候,不能定義編碼類型,即不能在open()函數內指定encoding。再補充一些文件操作的方法,具體如下:

with open("尼古拉斯趙四","wb") as f:

f.encoding() #文件的打開編碼,encoding=“”定義的是哪個編碼方式,輸出的就是哪個編碼方式,與源文件的編碼方式無關 #如果不知道源文件編碼,可以在定義時將encoding=“latin-1”,該編碼方式兼容大部分編碼 #f.flush() #刷新,當對文件進行修改操作的時候,通過此方法可以使更改生效(pycharm不需要此方法的原因是pycharm內部機制會自動保存) #f.tell() #打印光標所在的位置,光標移動 是以字節為單位,read()是以字符為單位,中文3個字節,英文一個字節 #with open("尼古拉斯趙四","w",encoding="utf-8",newline="") as f: 讀取源文件中真正的換行符,
                                          通過readlines方法讀取文件,不加newline=“”的話輸出\n,加上是\r\n
#f.seek(0) #指定光標的位置,在0處 # f.seek(10,0) #後面的是默認位置,即光標位置從0開始,以b的方式操作,因為seek是以字節為單位移動光標 # f.seek(10,1) #1代表的相對位置 # f.seek(3,1) #基於10移動光標 # f.seek(-5 ,2) #2代表倒序指定光標位置 # f.truncate(10) #從開頭截取到10 (光標位置) w\w+模式下不行

2.文件路徑

  如果程序文件存放在當前路徑下,那麽通過open("文件名稱")的方式就可以打開文件,但如果程序文件存放在其他路徑下或或當前文件的子目錄下,那麽就必須要提供文件路徑,它讓Python到系統中的特定位置去找。

  相對路徑

  假如:在當前路徑下有一個files文件,files文件下有一個“尼古拉斯趙四”這個程序文件,我如果想要打開這個文件,就需要使用相對文件路徑來打開它。

with open("files\尼古拉斯趙四",encoding="utf-8") as f:
    print(f.readlines())

  這行代碼讓Python去打開文件夾files下的“尼古拉斯趙四”這個文件,在Windows系統中,文件路徑使用反斜杠(\)而不是斜杠(/)

  絕對路徑

  可以將文件在計算機中的準確位置告訴Python,這樣就不用關心當前運行的程序存儲在什麽地方,這稱為絕對路徑。當相對路徑行不通時,可以使用絕對路徑。絕對路徑通常比相對路徑更長,在Linux系統中類似於這樣:/home/dir/files/1.txt;在Windows系統中類似於這樣:C:\Users\dir\files\1.txt

  通過使用絕對路徑,可讀取系統中的任何地方的文件。

3.叠代器

  叠代器和遞歸函數的區別:遞歸函數是不斷的重復調用自己,必須有一個明確的條件,而且每進行更深一層的循環,規模一定要較之前要小,叠代器,每次循環都要依賴於上一次的結果。

  叠代器協議:對象必須提供一個_next_()方法,執行該方法要麽返回叠代中的下一項,要麽就引起一個StopIteration異常(只能往後走不能往前退)。

  可叠代對象:實現了叠代協議的對象(如何實現?對象內部定義一個_iter_()方法)。

  協議是一種約定,可叠代對象實現了叠代器協議,python的內部工具(如for循環,sum,min,max函數等)使用叠代器協議訪問對象。

  以for循環舉例:for循環就遵循叠代器協議來循環所有的對象,(列表、字典、字符串、元組,集合)這些其實都不是可叠代對象,只不過在for循環時,調用了他們內部的_iter_方法,把他們變成了可叠代對象,然後for循環調用可叠代對象,然後就可以調用_next_()方法,直至異常結束,用代碼解釋如下:

name=[1,2,3]for i in name:         l=name.__iter__()   print(l.__next__())    print(i)

  在for循環列表的時候,實質上是調用了列表的內置方法_iter_(),將列表變成一個可叠代對象,成為可叠代對象後,該列表就有了_next_()方法,在調用此方法一個一個讀取。

  還有一個next()方法,其實質就是在調用_next_()函數。

  可以被next()函數調用並不斷返回值下一個值的對象就是叠代器:Iterator,列表,字典這些基本數據類型雖然是可叠代對象,但不是叠代器,可以通過_iter_()方法將它們變為叠代器。

name=[1,2,3]
print(type(name.__iter__()))           通過_iter_方法將可叠代對象變為叠代器
運行結果:
<class list_iterator>

4.列表生成式和三元運算

  列表生成式怎麽說呢,就是一種裝逼專用吧,我舉一個簡單的例子吧,我現在需求是輸出從1-9的數字,當然大部分人首先會想到for循環

name=[]
for i in range(10):
    name.append(i)
print(name)
運行結果:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]                   

  上面這個例子就不多解釋了,認真看過我前面博客的,這是很簡單的一個for循環,但如果我就嫌麻煩,這代碼太多了,我就要用一行寫出來,能不能辦到呢?

print([i for i in range(10)])       
運行結果:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]   

  ok,裝逼版本,這就是列表表達式。

  那麽什麽是三元運算呢?

name="尼古拉斯趙四"
print("會街舞" if name=="尼古拉斯趙四" else "不會街舞")        一元:“會街舞”  二元:通過if語句判斷   三元:“不會街舞”
輸出結果:
會街舞

  其實很好理解,if前面可以理解為判斷為True的返回結果,else後是判斷為False的返回結果,這就是三元運算。

  三元運算還可以與列表生成式結合使用,需求:輸出10以內大於5的數字

print([i for i in range(10) if i>5  ])
運行結果:
[6, 7, 8, 9]

  但註意一點,在這種語句,就不能在家else了,一定要註意三元,加上了else就變成四元了,程序會報錯的

5.生成器

  在Python中,一邊循環一邊計算的機制,稱為生成器(generator)。生成器可以理解為一種數據類型,這種數據類型自動實現的叠代器協議(其他的數據類型是通過調用自己的內置方法_iter_方法),所以生成器就是可叠代對象,直接就可以使用_next_()方法。

  生成器分類在python中的表現形式(python有兩種不同的方式提供生成器)

  1.生成器表達式,生成器其實就是把列表生成器的[]變為()。即上面的列表生成式,我要將它變為生成器的話:

print(type((i for i in range(10) if i>5  )))
運行結果:
<class generator>

  generator保存的是算法,每次調用next(),就計算出下一個元素的值,直到計算到最後一個元素,沒有更多的元素時,拋出StopIteration的錯誤。

a=(i for i in range(10) if i>5  )
print(a.__next__)
print(next(a))              每次執行一次next()操作,只會讀取一個值
print(next(a))
運行結果:
<method-wrapper __next__ of generator object at 0x000001620ECD7888>
6
7

  如果這個生成器有N多個值呢?一直用next()顯然是不方便的,所以一般都是用for循環。

  2.函數生成式

  只要在定義函數的時候,把return()變為yield()就可以了,yield()保存上一次讀取值的位置,當再次調用時,就從該位置開始調用。普通函數遇到return語句或者最後一行函數語句就返回。而變成generator的函數,在每次調用next()的時候執行,遇到yield語句返回,再次執行時從上次返回的yield語句處繼續執行。

def func():
    yield 1
    yield 2
res=func()
print(res.__next__())
運行結果:
1

  執行一次_next_()方法,輸出1,程序停留在此位置,當再次執行一次_next_()方法時,會從1的位置開始執行,再輸出2,這就是函數生成式。當執行_next_()讀取完全部元素後,再次執行程序就會拋出StopIteration異常,處理異常的方法我會在接下來的文章中詳細介紹。

Python函數篇(4)之叠代器與生成器