一、模塊使用
模塊就是用一堆代碼實現(xiàn)了某個功能的代碼集合,python中一個py文件就是一個模塊;模塊有三種類型:自定義模塊,內(nèi)置模塊,第三方模塊
1、自定義一個模塊
''' 自定義了一個my_math 模塊 '''
PI=3.14159
e=2.718
def fibo(n):
if n==1 or n==0:return 1
return fibo(n-1)+fibo(n-2)
def factorial(n:int):
result=1
for x in range(1,n+1):
result*=x
return result
if __name__=="__main__":
print(PI )
print(fibo(10))
print(factorial(5))
#執(zhí)行該模塊后的結(jié)果:
'''
3.14159
89
120
'''
注意:
若模塊中存在 if name == 'main':
直接執(zhí)行當前模塊,代碼塊會被執(zhí)行;如果在別的模塊中被導(dǎo)入,代碼塊不會執(zhí)行(阻止其他模式使用該模塊的代碼)
分析:
每一個模塊都有一個_ _name_ _屬性, 這個屬性的默認值是當前模塊對應(yīng)py文件的文件名;當當前模塊正被執(zhí)行(直接)的時候,系統(tǒng)會自動將模塊的_ _name_ _屬性變成'_ _main_ _'
2、模塊的使用
導(dǎo)入模塊:代碼執(zhí)行到import的時候,會將import后面的模塊的內(nèi)容執(zhí)行一遍;當兩個模塊中含有相同名稱函數(shù)或者變量的時候,后面一次引入會覆蓋前一次引入
(1)import 模塊名
將模塊中所有的內(nèi)容都導(dǎo)入,并且可以在當前模塊中通過'模塊名.'的方式去使用模塊中的所有全局變量
(2)from 模塊名 import 變量1, 變量2,
將模塊中所有的內(nèi)容都導(dǎo)入,但是只能使用import后面的變量
注意:通過這種方式引入的時候,調(diào)用函數(shù)時只能給出函數(shù)名,不能給出模塊名
(3)from 模塊名 import *
將模塊中所有的內(nèi)容都導(dǎo)入, 可以直接使用模塊中的所有全局變量
重命名:
(1)import 模塊名 as 模塊的新名字
給模塊重命名,使用模塊的時候用新的名字來使用
(2)from 模塊名 import 變量名1 as 新名1, 變量名2
給部分變量重新命名
import my_math as Math_mine
print(Math_mine.e,Math_mine.PI)
from my_math import *
print(fibo(10))
from my_math import PI as pi,e as E
print(pi,E)
二、迭代器
什么是迭代器
1.什么是迭代器(iter)
迭代器是python中一種容器類的數(shù)據(jù)類型,屬于序列。沒有具體的字面量,可以將其他的序列轉(zhuǎn)換成迭代器:iter(序列)
2.迭代器的特點
只能通過next方法去一個一個按順序獲取迭代器中的元素,取出后迭代器中就不存在這個元素了
任何實現(xiàn)了iter和next()方法的對象都是迭代器,iter返回迭代器自身,next返回容器中的下一個值;如果容器中沒有更多元素了,則拋出StopIteration異常
迭代器的使用
iter1 = iter('abcd')
print(iter1) #返回一個迭代器對象
print(next(iter1)) #獲取迭代器的值
print(next(iter1))
iter2 = iter((1, 2, 3))
a = iter2.__next__() #通過.__next__()方法
print(a) # 1
list1 = list(iter2)
print(list1) # [2, 3]
#遍歷迭代器
iter1 = iter(['abc', 10, 'name'])
print('=====')
for x in iter1:
print(x)
print('====')
小結(jié):
凡是可作用于for循環(huán)的對象都是Iterable類型;
凡是可作用于next()函數(shù)的對象都是Iterator類型,它們表示一個惰性計算的序列;
集合數(shù)據(jù)類型如list、dict、str等是Iterable但不是Iterator,不過可以通過iter()函數(shù)獲得一個Iterator對象。
Python的for循環(huán)本質(zhì)上就是通過不斷調(diào)用next()函數(shù)實現(xiàn)的
三、生成器
生成器其實是一種特殊的迭代器,不過這種迭代器更加優(yōu)雅,實質(zhì)就是函數(shù)體中有yield關(guān)鍵字的函數(shù)
生成器一定是迭代器(反之不成立),因此任何生成器也是以一種懶加載的模式生成值
從列表推導(dǎo)式說起....
若一個列表為:[1,2,3,4,5,6,7,8,9],要求把每一個元素都翻倍,實現(xiàn)的方式有三種:
#第一種:使用循環(huán)
info = [1, 2, 3, 4, 5, 6, 7, 8, 9]
for index,element in enumerate(info):
info[index] *=2
print(info)
#enumerate()--將一個可遍歷的數(shù)據(jù)對象組合為一個索引序列,同時列出數(shù)據(jù)和數(shù)據(jù)下標
#第二種:使用map()函數(shù)
info = [1, 2, 3, 4, 5, 6, 7, 8, 9]
a = map(lambda x:x*2,info)
for i in a:
print(i,end=" ")
#第三種:使用列表推導(dǎo)式
info = [1, 2, 3, 4, 5, 6, 7, 8, 9]
a = [i*2 for i in range(10)]
print(a)
思考:
若列表的數(shù)據(jù)很大(1000萬個元素),創(chuàng)建的時候占用了大量的內(nèi)存空間,但是又只需要用到前面1000個元,那后面絕大多數(shù)元素占用的空間都白白浪費了
所以,如果列表元素可以按照某種算法推算出來,那我們是否可以在循環(huán)的過程中不斷推算出后續(xù)的元素呢?這樣就不必創(chuàng)建完整的list,從而節(jié)省大量的空間,在Python中,這種一邊循環(huán)一邊計算的機制,稱為生成器:generator
生成器是一個特殊的程序,可以被用作控制循環(huán)的迭代行為,python中生成器是迭代器的一種,使用yield返回值函數(shù),每次調(diào)用yield會暫停,而可以使用next()函數(shù)和send()函數(shù)恢復(fù)生成器
生成器與一般函數(shù)的不同:
(1)生成器函數(shù)包含一個或者多個yield
(2)當調(diào)用生成器函數(shù)時,函數(shù)將返回一個對象,但是不會立刻向下執(zhí)行
(3)像iter()和next()方法等是自動實現(xiàn)的,可以通過next()方法對對象進行迭代
(4)一旦函數(shù)被yield,函數(shù)會暫停,控制權(quán)返回調(diào)用者
(5)局部變量和它們的狀態(tài)會被保存,直到下一次調(diào)用
(6)函數(shù)終止的時候,StopIteraion會被自動拋出
生成式
生成式就是生成器的一種特殊形式:(變量 for 變量 in 序列)
gen1 = (x*2 for x in range(5))
print('=========')
for item in gen1:
print(item)
gen2 = ([x, x*2] for x in 'abc')
print(next(gen2))
print('===========')
gen3 = (x for x in range(5) if x%2)
for item in gen3:
print(item)
生成器函數(shù)
也是用def定義的,利用關(guān)鍵字yield一次性返回一個結(jié)果,阻塞,重新開始
def gen4(n):
for x in range(n+1):
print("第{}次循環(huán):x={}".format(x,x))
yield x
if x % 2 :
yield "{}是奇數(shù)".format(x)
else:
yield "{}是偶數(shù)".format(x)
a=gen4(5)
print(a) #<generator object gen4 at 0x0000021D15D6D678>
print(a.__next__()) #執(zhí)行到y(tǒng)ield關(guān)鍵字,控制權(quán)返回調(diào)用者,并保持局部變量狀態(tài)
print(a.__next__()) #從yield關(guān)鍵字開始繼續(xù)執(zhí)行,遇到y(tǒng)ield關(guān)鍵字再次返回
'''
第0次循環(huán):x=0
0
0是偶數(shù)
'''
def gen5(n):
for x in range(n):
yield x, 2*x, 3*x
return "Done"
a=gen5(3)
print(next(a))
print(next(a))
print(next(a))
'''
(0, 0, 0)
(1, 2, 3)
(2, 4, 6)
'''
#思考:如何才能取到返回值Done?
#必須捕獲StopIteration錯誤,返回值包含在StopIteration的value
while True:
try:
x=next(a)
print('generator: ',x)
except StopIteration as e:
print("生成器返回值:",e.value) #生成器返回值: Done
break
#用生成器計算斐波拉契數(shù)列
def fibo(max):
n,a,b =0,0,1
while n < max:
yield b
a,b =b,a+b
n = n+1
return 'done'
for i in fibo(6):
print(i,end=",")
#創(chuàng)建一個generator后,基本上永遠不會調(diào)用next(),而是通過for循環(huán)來迭代,并且不需要關(guān)心StopIteration的錯誤
四、文件操作
使用文件可以做數(shù)據(jù)的持久化(本地化) ---> 數(shù)據(jù)庫文件,txt、json,plist,二進制文件
所有文件操作的過程:打開文件 --> 操作文件 --> 關(guān)閉文件
文件操作 -- 讀寫操作
讀 -> 取出文件中的數(shù)據(jù)
寫 -> 將數(shù)據(jù)寫到文件中
打開文件和關(guān)閉文件
open(file, mode='r',encoding=None)
a.file -> 文件路徑(必須傳參),決定需要打開的是哪個文件
絕對路徑(不推薦使用)
相對路徑: ./相對路徑 (相對路徑是相對當前py文件對應(yīng)的文件夾)
./ ---> 當前文件夾
../ --> 當前文件夾的上層文件夾
.../ --> 當前文件夾的上層文件夾的上層文件夾
b.mode -> 文件打開方式(不同的操作對應(yīng)不同的打開方式)
'r' --> 以只讀的形式打開文件, 文本
'rb'/'br' --> 讀操作,讀出來的數(shù)據(jù)是二進制形式的數(shù)據(jù)
'w' --> 以寫的形式打開文件(完全覆蓋)
'bw'/'wb' --> 寫操作,將二進制數(shù)據(jù)寫入文件
'a' --> 寫操作,追加
c.encoding -> 文本文件的編碼方式
utf-8 :幾乎支持所有的語言文字
gbk : 只支持英文
d.open函數(shù)的返回值,就被打開的文件對象
關(guān)閉文件: 文件對象.close()
f1 = open('./test1.txt', 'r', encoding='utf-8')
content = f1.read()
print(type(content), content)
content = f1.readline()
print(type(content), content)# #<class 'str'> 返回值為空,該文件打開后已經(jīng)被讀完
content = f1.readlines()
print(type(content), content) #<class 'list'> []
f1.close()
f2 = open('./test1.txt', 'w', encoding='utf-8')
f2.writelines(['abc\n', '123\n', 'aaaaa\n'])
with關(guān)鍵字
with open(文件路徑,打開方式,encoding=編碼方式) as 文件對象:
文件操作代碼
說明:打開文件執(zhí)行操作后自動關(guān)閉文件對象,防止操作過程中出現(xiàn)異常導(dǎo)致文件未關(guān)閉
with open("./file/libai.txt",'w',encoding='utf-8') as file1:
file1.write('床前明月光,\n疑是地上霜\n')
with open("./file/libai.txt",'r',encoding='utf-8') as file1:
content=file1.read()
print(content)
二進制文件操作
常見的二進制文件:視頻、音頻、圖片、壓縮包等
bytes -->字節(jié),python專門用來表示二進制數(shù)據(jù)類型
注意:二進制文件不能設(shè)置文件編碼方法(不能給encoding賦值)
作用:下載或上傳文件
with open('./file/chengfabiao.png','rb') as file2:
content=file2.read()
print(type(content),content)
with open('./file/chengfabiao_copy.png','wb') as file2:
file2.write(content)
思考:讀取或?qū)懭霐?shù)據(jù)量為10G的文件,如何做?