文件處理

1.文件處理流程

a.打開文件,獲得文件句柄並賦值給一個變量

b.經過句柄對文件進行操做

c.關閉文件

f = open('123', encoding='utf8') #pycharm默認將文件以utf8格式編碼到硬盤上,雖然python3的編碼是utf8,
# 但open函數會去檢索當前系統的編碼,
# 當前系統是windows,因此open打開文件時用gbk解碼,open加的是文件的絕對路徑
data = f.read()
print(data)
f.close()

2.文件打開模式

a.r  讀操做 

f = open('123', encoding='utf8')
print('第1行', f.readline())#readline一行一行讀,讀的行數超出文本行數會顯示空
print('第2行', f.readline(), end='')#end=''能夠去掉換行
print('第3行', f.readline())
print('第4行', f.readline())
print('第5行', f.readline())
print('第6行', f.readline())
f = open('123', encoding='utf8')
data = f.read()
print('第1行', f.readline())#read和readline組合,readline會獲得空,由於 read是 讀取所有,已經讀到文件最後了
f = open('123', encoding='utf8')
data = f.readlines()
print(data)#返回值是全部行以列表形式呈現

b.w寫操做

f = open('123', 'w', encoding='utf8')#w模式:文件不存在,會自動新建一個新文件;文件存在,會清空掉文件內容再作操做
f.write('11111111\n')#write的參數必須是字符串
f.write('22222222\n')
f.write('333\n444\n555\n')
print(f.writable())
f.writelines(['666\n', '777\n'])#傳入的參數需爲列表
f.close()

c.a追加操做:在文件最後一個位置追加

f = open('123', 'a', encoding = 'utf8')
f.write('最後啦')
f.close

 d.r+可讀可寫

f = open('123', 'r+', encoding='utf8')
data = f.read()
print(data)
f.write('123')#默認從光標起始位置覆蓋

 文件無修改,文件在硬盤上以二進制形式存儲,修改文件實際是覆蓋操做,修改文件步驟:python

經過軟件打開文件(將文件的內容從硬盤加載到內存),在內存中能夠修改文件內容,改完後由軟件保存(將文件內容覆蓋回去)linux

模擬文件修改過程:編程

src_f = open('123', 'r', encoding='utf8')
data = src_f.readlines()
src_f.close

dst_f = open('123', 'w', encoding='utf8')
# dst_f.writelines(data)
dst_f.write(data[0])
dst_f.close

 with +open中with表示close的意思windows

with open('a.txt', 'w') as f:
f.write('1111\n')
with open('123', 'r', encoding='utf8') as src_f, \
open('123_new', 'w', encoding='utf8') as dst_f:
data = src_f.read()
dst_f.write(data)

 e.文件處理模式b模式 

f = open('123', 'rb', encoding='utf8')#b的方式不能指定編碼
f = open('123', 'rb')
data = f.read()
print(data)#windows中的換行是\r\n,linux中的換行是\n
#字符串 encode 二進制bytes
#二進制bytes decode 字符串
print(data.decode('utf8'))
f.close
f = open('123', 'wb')
f.write(bytes('gggg\n', encoding='utf8'))#編碼方式一bytes函數
f.write('啦啦'.encode('utf8'))#編碼方式二encode函數
f = open('123', 'ab')
f.write(bytes('gggg\n', encoding='utf8'))#編碼方式一bytes函數
f.write('啦啦'.encode('utf8'))#編碼方式二encode函數

b模式能夠打開不一樣文件類型(視頻、圖片、文本等),不帶b模式默認以文本模式打開app

b模式能夠跨平臺函數

b模式對Linux系統沒有用,由於Linux默認就是以二進制處理的工具

f.文件操做的其餘方法

closed 判斷文件是不是關閉狀態編碼

f.closed #文件若是關閉則返回True

encoding 取的是文件打開的編碼,跟原文件以什麼編碼方式存到硬盤上沒有關係code

f.encoding #查看使用open打開文件的編碼

flush 視頻

 f.flush() #講文件內容從內存刷到硬盤

tell當前光標位置

 f.tell() #查看文件處理當前的光標位置
f = open('a.txt', 'r', encoding='gbk')
print(f.closed)
print(f.encoding)
print(f.tell())
f.readline()
print(f.tell())

 newline讀取文件中真正的換行符號

f = open('a.txt', 'r', encoding='utf8', newline='')#若是不加newline,讀出的換行符號爲\n,這是pycharm默認處理的結果
print(f.readlines())

read方法處理文件時按字符讀取,其他的文件內光標移動都是以字節爲單位

seek

f.seek(3) #從開頭開始算,將光標移動到第三個字節

truncate截取

 f.truncate(10) #從開頭開始算,將文件只保留從0-10個字節的內容,文件必須以寫方式打開,可是w和w+除外,由於它們一打開文件,內容都被清空了

 seek的三種模式:

a.0模式:從頭開始seek

f=open('seek.txt', 'r', encoding='utf8')
print(f.tell())#剛打開文件,文件的光標就在0的位置
f.seek(10)
print(f.tell())#seek到哪,打印就到哪
f.seek(3, 0)#默認都是從0開始seek
print(f.tell())

 b.1模式:從上次光標的位置開始seek

f=open('seek.txt', 'rb')#seek0模式不須要以b的方式打開,其餘模式須要以b的方式打開
print(f.tell())#剛打開文件,文件的光標就在0的位置
f.seek(10, 1)
print(f.tell())
f.seek(3, 1)
print(f.tell())

 c.2模式:從文件末尾開始seek

f=open('seek.txt', 'rb')#seek0模式不須要以b的方式打開,其餘模式須要以b的方式打開
print(f.tell())#剛打開文件,文件的光標就在0的位置
f.seek(-5, 2)#倒着seek,要以負數的方式顯示
print(f.read())

 需求 :讀取文件最後一行 

方法1:

f = open('seek.txt', 'rb')
data = f.readlines()#很是佔內存
print(data[-1].decode('utf8'))

 方法2:

f = open('seek.txt', 'rb')
for i in f:#循環文件的推薦方式,省內存,一條一條的取,不符合就棄掉
offs = -10 #定義偏移量
while True:
f.seek(offs, 2)
data = f.readlines()
if len(data) > 1:
print('文件的最後一行是%s' %(data[-1].decode('utf8')))
break
offs*=2

3.迭代器協議和for循環工做機制

a.遞歸:本身調本身

b.迭代:被for循環遍歷

c.迭代器協議:對象必須提供一個next方法,執行該方法要麼返回迭代中的下一項,要麼就引發一個StopIteration異常,以終止迭代(只能日後走不能往前退)

d.可迭代對象:實現了迭代器協議的對象(如何實現:對象內部定義一個_iter_()方法)

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

f.for 循環的本質:循環全部對象,全都是使用迭代器協議

g.字符串、列表、元組、字典、集合、文件對象都不是可迭代對象,只不過在for循環時,調用了它們內部的_iter_(或iter())方法,把它們變成了可迭代對象

而後for循環調用了可迭代對象的_next_方法去取值,並且for循環會捕捉StopIteration異常,以終止迭代 

x = 'hello'
iter_test = x.__iter__()
print(iter_test)
print(iter_test.__next__())
print(iter_test.__next__())
print(iter_test.__next__())
print(iter_test.__next__())
print(iter_test.__next__())
print(iter_test.__next__())#會報錯

h. for 循環能夠遍歷列表,while循環也能夠遍歷列表

l = [1, 2, 3]
index = 0
while index < len(l):
print(l[index])
index += 1

i.爲何要有for循環?

序列類型字符串、元組、列表都有下標,用while循環能夠遍歷;但非序列類型字典、集合、文件沒辦法用while循環來作,for循環基於迭代器協議提供了一個統一的能夠遍歷全部對象的方法

s = {1, 2, 3}
iter_s = s.__iter__()
print(iter_s.__next__())
dic = {'a': 1, 'b': 2}
iter_d = dic.__iter__()
print(iter_d.__next__())#返回值是key值

j.用while模擬for循環作的事情

l = [1, 2, 3, 4, 5]
iter_l = l.__iter__()
while True:
try:
print(iter_l.__next__())
except StopIteration:
print('迭代完成了')#for循環不打印這一句
break

k.next()函數

l = ['father',  'son', 'grandson', 'grandgrandson']#佔內存方式 :全部內容都放到內存裏
iter_l = l.__iter__()#佔內存方式:迭代器對象
# print(iter_l.__next__())
# print(iter_l.__next__())
# print(iter_l.__next__())
# print(iter_l.__next__())
# print(iter_l.__next__())
print(next(iter_l))#next(python內置函數)至關於調用iter_l.__next__()(數據類型內置的)

4.生成器 

a.生成器定義

能夠理解爲一種數據類型,這種數據類型自動實現了迭代器協議(其餘數據類型須要調用本身內置的__iter__方法),因此生成器就是可迭代對象

b.生成器分類及在python中的表現形式(pyhton有兩種不一樣的方式提供生成器)

1.生成器函數:常規函數定義,可是,使用yield語句而不是return語句返回結果。yield語句一次返回一個結果,在每一個結果中間,掛起函數的狀態,以便下次從它離開的地方繼續執行

def test():
yield 1
yield 2
yield 3
g = test()
print(g)

2.生成器表達式:

hen = ('雞蛋%s' %i for i in range(10))#生成器表達式直接實現迭代器協議,節省內存
print(hen)
print(hen.__next__())
print(next(hen))
print(hen.__next__())
print(next(hen))

c.三元表達式/三元運算

name = 'cyx'
res = 'gb' if name == 'cyx' else 'gg'#三元表達式
print(res)

d.列表解析

l = ['a' for i in range(10)]#循環十次,依次把a放到這個列表中
print(l)

需求:用一行代碼代替如下代碼

egg_list = []
for i in range(10):
egg_list.append('雞蛋%s' %i)
print(egg_list)
l = ['雞蛋%s' %i for i in range(10)]
print(l)
l = ['雞蛋%s' %i for i in range(10) if i > 5]#列表解析裏能夠用三元表達式
print(l)
l = ['雞蛋%s' %i for i in range(10) if i > 5 else i]#沒有四元表達式,能夠有兩元

列表解析的缺點:生成的就是列表,會佔內存

總結:把列表解析的[]換成()獲得的就是生成器表達式

列表解析與生成器表達式都是一種便利的編程方式,只不過生成器表達式更節省內存

python不但使用迭代器協議使for循環變得更加通用,大部份內置函數也是使用迭代器協議訪問對象的

print(sum(i**2 for i in range(5)))

 補充:生成器只能遍歷一次

def test():    for i in range(4):        yield it = test()for i in t:    print(i)t1 = (i for i in t)print(list(t1))#生成器只能遍歷一次,因此輸出結果爲[]
相關文章
相關標籤/搜索