【python 2】python 进阶
文章目錄
- 一、函數
- 1、函數的參數
- 2、全局變量和局部變量
- 3、內部函數
- 4、閉包
- 5、匿名函數
- 6、系統自帶的函數
- 7、遞歸函數
- 二、文件操作
- 三、os 模塊
- 1、os.path
- 2、os 里邊的函數
- 四、異常
- 五、推導式
- 1、列表推導式
- 2、集合推導式
- 3、字典推導式
- 六、生成器
- 七、迭代器
一、函數
def 函數名():函數體調用:函數名() —>找到函數,并執行函數體的內容
寫了函數名() 就是調用,調用的過程是,系統先順著名字找到地址,找到地址就找到了內容,之后執行內容。
1、函數的參數
定義: def 函數名(參數):函數體調用:求隨機數的函數,產生的個數不確定:
定義的時候定義的參數:形參(占位)
調用的時候需要的參數:實參(具體的參數)
練習 1:封裝一個用戶登陸函數
''' 定義一個登陸函數,參數是 uername, password 函數體: 判斷參數傳過來的 username、password 是否正確,如果正確則登陸成功,否則登陸失敗 ''' # 函數的定義 def login(username, password):uname = 'admin123'pword = '112233'for i in range(3):if username == uname:print('登陸成功!')breakelse:print('用戶名或密碼不匹配,登陸失敗!')username = input('請輸入用戶名:')password = input('請輸入密碼:')else:print('超過三次錯誤,用戶鎖定!')# 函數的調用 username = input('請輸入用戶名:') password = input('請輸入密碼:') login(username, password) >>> 請輸入用戶名: admin123 請輸入密碼: 112233 登陸成功!練習 2:封裝一個求最大值的函數
# 定義 def max(iterable):max = iterable[0]for i in iterable:if i > max:max = iprint('最大值是:', max) # 調用 list1 = [3,6,3,2,7] max(list1) >>> 最大值是: 7 # 定義 def min(iterable):min = iterable[0]for i in iterable:if i < min:min = iprint('最小值是:',min) # 調用 list1 = [3,6,3,2,7] min(list1) >>> 最小值是: 2判斷是不是 list、tuple等類型:isinstance()
# isinstance(名稱,類型) print(isinstance(list1,list)) >>> True練習3:模擬 enumerate
s = [1,3,5,7,9] for i in s:print(i) print('-----------------') for index,value in enumerate(s):print(index,value) print('-----------------') list1 = [] index = 0 for i in s:t1 = (index,i)list1.append(t1)index+=1 print(list1) print('-----------------') for index,value in list1:print(index,value) >>> 1 3 5 7 9 ----------------- 0 1 1 3 2 5 3 7 4 9 ----------------- [(0, 1), (1, 3), (2, 5), (3, 7), (4, 9)] ----------------- 0 1 1 3 2 5 3 7 4 9 # 定義 def enumerate(value):list1 = []index = 0for i in value:t1 = (index,i)list1.append(t1)index += 1for index,value in list1:print(index,value) #調用: value = [1,3,5,7,9] enumerate(value) >>> 0 1 1 3 2 5 3 7 4 9列表是可變的,字符串是不可變的,
# 列表可變 list1 = [1,2,3,4] list2 = list1 list1.remove(3) print(list2) >>> [1, 2, 4] # 字符串不可變 s1 = 'abc' s2 = s1 s1 = 'abcd' print(s2) >>> abc可變參數的定義方式:
# 定義 def add(*args):print(args) # 調用 add() add(1,) add(1,2) >>> () # 空元組 (1,) (1, 2)可變參數必須放在不可變參數的后面
def add(name, *args):print(name, args) add('aa',1,2,3) >>> aa (1, 2, 3)默認值:
def add(a, b=10):result = a+bprint(result) add(3) add(4,7) # b=7,會覆蓋掉默認的b=10 >>> 13 11 # 想給c賦值,不想給b賦值,通過關鍵字賦值 def add1(a,b=10,c=4):result = a+b+cprint(result) add1(2,c=10) >>> 22打印每位同學的姓名和年齡:
students={'001':('王俊凱', 20),'002':('易烊千璽',19), '003':('王源',19)} def print_boy(person):if isinstance(person, dict):for name, age in person.values():print('{}的年齡是: {}'.format(name,age)) print_boy(students) >>> 王俊凱的年齡是: 20 易烊千璽的年齡是: 19 王源的年齡是: 19關鍵字參數:
# **kwargs:關鍵字參數,必須按 a=10,c=9 這樣來賦值 # 得到字典形式的結果 def func(**kwargs):print(kwargs) func(a=1,b=2,c=3) >>> {'a': 1, 'b': 2, 'c': 3}能用字典傳入嗎?
給函數賦值的時候,傳遞實參的時候,用到 ** 的時候,把這個字典拆包,拆成關鍵字的形式。拆成 001=python, 003=java…,
dict = {'001':'python','002':'java','003':'c++','004':'go'}def func1(**kwargs):print(kwargs) # 調用 func1(**dict) >>> {'001': 'python', '002': 'java', '003': 'c++', '004': 'go'}使用的時候:
調用的時候用 **dicts:拆包, 穿實參的時候加 **,系統會先拆成關鍵字的形式(001=python,002=java…)
定義的時候用 **kwargs:裝包,把拆完的又給裝成字典
函數返回值:將函數運算的結果,利用return的形式返回來,return result。
# 把函數的輸出結果扔出來 def add(a,b):result1 = a+breturn result1 result = add(1,2) print(result) >>> 3練習 1:加入購物車
''' 加入購物車 判斷用戶是否登錄,如果登錄,則成功加入購物車,如果沒有登陸,則提示登陸之后再添加 ''' islogin = False # 用于判斷用戶是否登錄的變量,默認是沒有登陸的 def add_shoppingcart(goodsName):global isloginif islogin:if goodsName:print('成功加入購物車!')else:print('登陸成功,沒有選中任何商品!')else:answer = input('用戶沒有登陸,是否登陸?(y/n)')if answer == 'y':username = input('請輸入用戶名:')password = input('請輸入密碼:')islogin = login(username, password)else:print('很遺憾,不能添加任何商品!') def login(username, password):if username == '李佳琪' and password == '123456':return Trueelse:print('用戶名或密碼有誤,請重新輸入:')return False# 調用函數,添加到購物車 username = input('請輸入用戶名:') password = input('請輸入密碼:') islogin = login(username, password) add_shoppingcart('阿瑪尼唇釉') >>>請輸入用戶名: 離 請輸入密碼: ww 用戶名或密碼有誤,請重新輸入: 用戶沒有登陸,是否登陸?(y/n) y 請輸入用戶名: 李佳琪 請輸入密碼: 123456驗證碼驗證:
def generate_checkcode(n):s = '0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM'code = ''for i in range(n):ran = random.randint(0,len(s)-1)code += s[ran]return code def login():username = input('輸入用戶名:')password = input('請輸入密碼:')code = generate_checkcode(5)print('驗證碼是:',code)code1 = input('請輸入驗證碼!')# 驗證if code.lower() == code1.lower():if username == 'lijiaqi' and password == '123456':print('用戶登陸成功!')else:print('用戶名或密碼有誤!')else:print('驗證碼輸入錯誤') login() >>> 輸入用戶名: lijiaqi 請輸入密碼: 123456 驗證碼是: Wavvv 請輸入驗證碼! Wavvv 用戶登陸成功!2、全局變量和局部變量
局部變量:函數內部聲明的變量,只能在函數體內改變
全局變量:聲明在函數外側的,所有函數都可以訪問,在函數體中不能修改,如果要改,要在函數的開頭加 global name,只有修改的時候,才需要加。
什么情況加 global:全局變量是不可變的(字符串、float等)但要修改的時候,需要加 global。如果全局變量是可變的,比如 list、修改的時候是不用加 global 的。
3、內部函數
在函數里邊又聲明一個函數,這個內部函數就是在大函數里邊的。
特點:
- 內部函數可以訪問這個函數中聲明的變量
- 內部函數可以修改外部函數的可變類型的變量,比如list
- 內部函數不能修改外部函數的不可變變量,要修改得加 nonlocal。
- 內部函數不能修改全局變量,要修改得在內部函數里邊加 global.
修改全局變量: global a
修改局部變量: nonlocal b
locals() 函數:是一個內置函數,可以查看當前函數中聲明內容有哪些
locals() 輸出的形式: key:values
globals() 函數:查看全局變量有哪些,以字典的形式輸出。
4、閉包
閉包是在函數中提出的概念,也就是在外部函數的外部訪問內部函數。
閉包的格式:在函數里邊定義了一個內部函數,把內部函數通過 return 給扔出來了,就叫閉包。
閉包的條件:
- 必須要有內部函數
- 內部函數必須引用外部函數的變量
- 外部函數是有返回值的,返回的值是內部函數名
格式:
def 外部函數():...def 內部函數():...return 內部函數名 def func():a = 100def inner_func():b = 90print(a,b)return inner_func # 調用,相當于把 inner_func 給了a,a就是內部函數了,然后調用該內部函數,就給 a 加括號就好啦 a = func() a() >>> 100 90 def func(a,b):c = 10def inner_func():s = a+b+cprint('相加之和的結果是:', s)return inner_func ifunc = func(6,9) ifunc() ifunc = func(5,6) ifunc() >>> 相加之和的結果是: 25 相加之和的結果是: 21閉包的特點:
- 能夠保存返回閉包時的狀態,不會受后面輸入參數變化的影響。
5、匿名函數
簡化函數的定義
定義格式:lambda 參數1,參數2 : 運算
有lambda,底層就會給你創建一個函數,這個函數是沒有名字的,匿名的,前面是參數,:后面的就相當于 return 返回的結果。
# s 是一個函數 s = lambda a,b : a+b result = s(1,2) print(result) >>> 3匿名函數可以作為參數:
def func(x, y, func):print(x, y)print(func)s = func(x, y)print(s) func(1, 2, lambda a, b : a + b) >>> 1 2 <function <lambda> at 0x0000023896096378> 3 list1 = [3,4,5,6,8] m = max(list1) print('列表最大值:',m) list2 = [{'a':10,'b':20},{'a':13,'b':20},{'a':9,'b':20},{'a':29,'b':20}] # 找 a 的最大值 m = max(list2, key = lambda x:x['a']) print('列表的最大值:',m) >>> 列表最大值: 8 列表的最大值: {'a': 29, 'b': 20}6、系統自帶的函數
1、map() 函數,對列表中元素進行操作,免去了之前的for循環
# map(操作函數,操作對象) map(lambda ..., list1) list1 = [3,4,5,6,7,9] result1 = map(lambda x : x+2, list1) print(list(result1)) >>> [5, 6, 7, 8, 9, 11]如果是偶數,則返回偶數本身,如果不是偶數,則進行+1操作:
# 方法一 func = lambda x : x if x%2 == 0 else x+1 result = func(5) print(result) >>> 6 # 方法二,對列表中的奇數進行+1,偶數不變 result = map(lambda x : x if x%2 == 0 else x+1, list1) print(list(result)) >>> [4, 4, 6, 6, 8, 10]2、reduce() 函數,對列表(可迭代的)中的元素進行 ±*/
from functools import reduce tuple1 = (3,5,6,7,8) result = reduce(lambda x, y: x+y, tuple1) print(result) >>> 293、filter() 函數,過濾符合條件的元素,且原始的list不會被改變
list1 = [3,4,5,6,8] result = filter(lambda x:x>5, list1) print(list(result)) >>> [6, 8] students = [{'name':'lucy','age':21},{'name':'tomy','age':20},{'name':'jack','age':19},{'name':'json','age':18},] result = filter(lambda x:x['age']>20,students) print(list(result)) >>> [{'name': 'lucy', 'age': 21}]按照年齡從小到大排序:
result = sorted(students, key=lambda x:x['age']) print(result) >>> [{'name': 'json', 'age': 18}, {'name': 'jack', 'age': 19}, {'name': 'tomy', 'age': 20}, {'name': 'lucy', 'age': 21}]總結:
max(), min(), sorted():都可以結合key來選擇
map():將列表中的每個元素進行統一操作
reduce(): 對列表中的元素進行累加啊
filter():過濾
7、遞歸函數
普通函數:def func(): pass
匿名函數: lambda 參數:返回結果
遞歸函數:普通函數的一種表現形式,函數自己調用自己
遞歸函數的特點:
- 一定要有終點(加判斷)
- 通常都會有一個入口
二、文件操作
1、mode:
- r : read 讀,純文本文件
- w: write 寫,純文本文件
- rb:read binary 二進制讀,包括純文本、圖片、音樂、MV等
- wb:write binary 二進制寫
- a: append 追加
這里的讀寫,其實就是確定管道的類型:讀、寫
系統函數:
open(file, mode, buffering...)open 就相當于給 file.txt 和 pycharm 建立了一個管道,.read() 就相當于把文件中的東西給讀出來,通過管道傳遞出來。
2、讀
stream = open(filename, 'r') # 返回值是一個stream,流管道 # 然后用 read 去讀 container = stream.read() stream = open(r'file.txt') # .read() 讀所有內容 container = stream .read() print(container) # .readable() 判斷是否可以讀取 container = stream.readable() print(container) >>> hello world! hello kitty! hello May! ----------------------- True ----------------------- stream = open(r'file.txt') # .readline() 一行一行讀 line = stream.readline() print(line) >>> hello world!readline() 通常用 for 循環
stream = open(r'file.txt') while True:line = stream.readline()print(line)if not line:break >>> hello world!hello kitty!hello May! # .readlines(),全部讀取,保存在列表里 stream = open(r'file.txt') lines = stream.readlines() print(lines) print('---------------------------') for i in lines:print(i) >>> ['hello world!\n', 'hello kitty!\n', 'hello May!'] --------------------------- hello world!hello kitty!hello May!讀取圖片,要使用 rb 方式
stream = open(r’image.jpg’,‘rb’)
container = stream.read()
3、寫
寫
- stream.write('內容‘)
- stream.writelines(Iterable),沒有換行的效果,可以自己加\n
特點:
- 在對 stream 的操作時,都會把原來的內容覆蓋掉。也就是上次寫的內容覆蓋掉,但不會把這一次讀寫的內容覆蓋掉。
從得到一個 stream 到關閉這個 stream 叫一次讀/寫,這一次的讀/寫中,可以多次對這個 stream 進行操作。
stream = open('file.txt','w') s = 'hello xiao ming!' stream.write(s) stream.write('hello xiao hua!') stream.close()換行寫:
stream = open('file.txt','w') stream.write('hello jenny!') stream.writelines(['hello denny!\n','hello xiao hong!\n'])
4、追加模式 a
在寫的時候,不會把之前的內容擦掉,會在后面追加
stream = open('file.txt','a') stream.write('hello jenny!\n') stream.writelines(['hello denny!\n','hello xiao hong!\n'])
5、文件的復制
原文件:\img\image.jpg
目標文件:\img\image1.jpg
每次要打開,要關閉 stream 會比較麻煩,可以直接用 with,with可以幫助我們自動釋放資源。
with open('image.jpg','rb') as stream:container = stream.read()with open('image1.jpg','wb') as wstream:wstream.write(container) print('文件復制完成!') >>> 文件復制完成!三、os 模塊
operation system
模塊的概念:.py就是一個模塊
stream.name 可以得到文件的路徑+名稱
os.path:
- os.path.dirname(‘file’) :獲取當前文件所在的文件目錄(絕對路徑)
- os.path.join(path,‘img.jpg’):返回一個拼接后的新路徑
1、os.path
os.path
- absolute:絕對路徑
- 表示當前文件的上一級,…/
獲取文件所在文件夾的當前路徑:
path = os.path.dirname('__file__') print(path) >>> C:\Users\man.wang\python\python\part4.py獲取絕對路徑:
path = os.path.abspath('file.txt') print(path) >>> C:\Users\man.wang\python\python\file.txt獲取當前文件的絕對路徑:
path = os.path.abspath('__file__') print(path)獲取當前文件的文件夾所在的路徑:
path = os.getcwd() # print(path) >>> C:\Users\man.wang\python\python文件名切分:split
- os.path.split(path):把文件名前的路徑和文件名分別存成元組的兩個元素
- os.path.splitext():文件和擴展名分開,存放成元組的兩個元素
得到文件的大小,單位是字節個數:
- os.path.getsize(path)
2、os 里邊的函數
獲取當前文件所在的目錄:os.getcwd()
result = os.getcwd() print(result) >>> C:\Users\man.wang\python\python獲取文件夾中的所有文件/文件夾的名字:os.listdir()
path = r'C:\Users\man.wang\python\python' result = os.listdir(path) print(result) >>> ['.ipynb_checkpoints', 'file.txt', 'image.jpg', 'image1.jpg', 'image2.jpg', 'p1', 'p2', 'part 1.ipynb', 'part2.ipynb', 'part3.ipynb', 'part4.ipynb']創建文件夾:os.mkdir(),如果存在則報錯
所以用 os.mkdir() 時候,最好先判斷文件夾是否存在
dirc = 'p3' if not os.path.exists(dirc):os.mkdir('p3')刪除空文件夾:os.rmdir()
os.rmdir('p3')刪除非空文件夾:要一層一層的刪 os.removedirs('p3)
刪除文件:os.remove()
os.remove(r'C:\Users\man.wang\python\python\p1\image.jpg') # 刪除 p1 文件夾中的所有文件 path = r'C:\Users\man.wang\python\python\p1' filelist = os.listdir(path) for file in filelist:path1 = os.path.join(path,file)os.remove(path1) # 刪除p1 else:os.rmdir(path)print('刪除成功') >>> 刪除成功切換目錄:os.chdir()
# 切換目錄,可以切換到指定目錄下 f = os.chdir(r'C:\Users\man.wang\python\python\p2') print(os.getcwd()) >>> C:\Users\man.wang\python\python\p2四、異常
語法沒報錯,運行的時候報錯
def chu(a,b):return a/b chu(1,0) >>> ZeroDivisionError: division by zero異常處理:
try:可能出現異常的代碼 except:如果有異常,則執行此處的代碼 finally:無論是否存在異常,都會被執行的代碼如果不加異常,這段代碼有問題的話,下面的所有的代碼都不會被執行。
def func():try:n1 = int(input('輸入第一個數字:'))n2 = int(input('輸入第二個數字:'))# 加法result = n1 + n2print('兩數之和為:',result)except:print('必須輸入數字!') func() >>> 輸入第一個數字: 2 輸入第二個數字: w 必須輸入數字! def func():try:n1 = int(input('輸入第一個數字:'))n2 = int(input('輸入第二個數字:'))oper = input('請輸入運算符號:(+-*/)')result = 0if oper == '+':result = n1 + n2elif oper == '-':result = n1 - n2elif oper == '*':result = n1 * n2elif oper == '/':result = n1 / n2else:print('符號輸出錯誤!')print('結果為:',result)except ZeroDivisionError:print('除數不能為 0!')except ValueError:print('必須輸入數字!') func() >>> 輸入第一個數字: 1 輸入第二個數字: 0 請輸入運算符號:(+-*/) / 除數不能為 0!如果用了 else,在 try 代碼中不能出現 return,如果走了 try,然后直接就終止代碼了。
情況1:
try:pass except:pass情況2:打印錯誤原因
try:pass except Exception as err:print(err)情況3:沒有異常的時候,會執行的 else 的代碼,但 try 里邊不能用 return,因為沒有異常的時候,
try:pass except ValueError:pass else:print('')異常拋出:
# 實現用戶名小于6位時拋出異常 def register():username=input('請輸入用戶名:')if len(username)<6:raise Exception('用戶名長度必須6位以上!')else:print('輸入的用戶名是:',username) register() >>> input-> www Exception: 用戶名長度必須6位以上!五、推導式
從舊的列表推導得到一個新的列表
1、列表推導式
格式:
- [表達式 for 變量 in 舊列表]
- [表達式 for 變量 in 舊列表 if 條件]
符合 if 條件的變量,扔到最前面的表達式中
# 過濾掉長度 <= 3 的人名 names = ['tom','lily','jack','json','bob'] # 第一個 name 就放的是names中符合長度 >3 條件的 name result = [name for name in names if len(name)>3] print(result)result = [name.capitalize() for name in names if len(name)>3] print(result)result = [name.title() for name in names if len(name)>3] print(result) >>> ['lily', 'jack', 'json'] ['Lily', 'Jack', 'Json'] ['Lily', 'Jack', 'Json'] # 列表推導式等價實現 names = ['tom','lily','jack','json','bob'] new_name=[] def func(names):for name in names:if len(name)>3:name = name.title()new_name.append(name)return new_name func(names) >>> ['Lily', 'Jack', 'Json'] # 將 1~100 之間,能被 3 整除的扔出來 newlist = [i for i in range(1,101) if i%3 == 0] print(newlist) >>> [3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99] # 將 1~100 之間,能被 3 整除,并且能被5整除的拿出來放到一個列表 newlist = [i for i in range(1,101) if i%3 == 0 and i%5 == 0] print(newlist) >>> [15, 30, 45, 60, 75, 90] # 求 0~5 之間的偶數,和 0~5 之間的奇數,構成一個元組,放到列表里邊 def func():new_list=[]for i in range(5):if i%2 == 0:for j in range(5):if j%2 != 0:new_list.append((i,j))return new_list func() >>> [(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)] # 列表推導式寫 # 在for后面再寫for,就相當于循環中的嵌套 new_list = [(x,y) for x in range(5) if x%2==0 for y in range(5) if y%2 != 0] print(new_list) >>> [(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]練習:不帶條件的列表推導式,直接取就好啦
''' list1 = [[1,2,3],[4,5,6],[7,8,9]] -----> list2=[3,6,9] ''' list1 = [[1,2,3],[4,5,6],[7,8,9]] new_list = [i[-1] for i in list1] print(new_list) >>> [3, 6, 9]練習:帶 else 的列表推導式,把 for 放到最后
dict1={'name':'tom','salary':5000} dict2={'name':'lili','salary':8000} dict3={'name':'jack','salary':3000} list1 = [dict1, dict2, dict3] # 如果薪資 > 5000 加工資 200,低于等于 5000 加工資 500 new_list = [person['salary']+200 if person['salary']>5000 else person['salary']+500 for person in list1 ] print(new_list) >>> [5500, 8200, 3500]2、集合推導式
# 遍歷 list 里邊的元素,把元素放到集合里邊,相當于去重 list1 = [1,2,3,4,5,6,3,1,2,3] set1 = {x for x in list1} print(set1)set2 = {x+1 for x in list1 if x>3} print(set2) >>> {1, 2, 3, 4, 5, 6} {5, 6, 7}3、字典推導式
# key 和 value 進行交換 dict1 = {'a':'A','b':'B','c':'C','d':'C'} new_dict = {value:key for key,value in dict1.items()} print(new_dict) >>> {'A': 'a', 'B': 'b', 'C': 'd'}六、生成器
通過列表生成式(列表推導式),可以直接創建一個列表,但是,收到內存的限制,列表容量肯定是有限的,而且,創建一個包含100w個元素的列表,不僅占用很大的存儲空間,如果我們僅僅需要訪問前面幾個元素,那后面的大多數元素占用的空間就白白浪費了。所以,如果列表元素可以按照某種算法推算出來,那我們是否可以在循環的過程中不斷推算后續的元素呢,這樣就不必創建整個list了,從而能夠大量的節省空間,在 python 中,這種一邊循環,一邊計算的機制,成為生成器(generator)。
得到生成器的方式:
- 通過列表推導式得到生成器(用小括號)
使用一個循環來搞定:
g = (x*3 for x in range(10)) while True:try:e = next(g)print(e)except:print('沒有更多元素啦!')break >>> 0 3 6 9 12 15 18 21 24 27 沒有更多元素啦!yield():函數里邊有yield,說明函數就不是函數了,就變成了生成器
''' 使用函數得到生成器:1、定義一個函數,函數中使用yield2、調用函數,并接收調用的結果3、得到生成器4、借助 next()/__next()__ 得到元素 ''' # 調用 func() 的時候是不會走到函數里邊去的 # 只有用 next() 的時候才會走到函數里邊 def func():n = 0while True:n += 1yield n # return+暫停 g = func() >>> <generator object func at 0x000002BFF923EC78> # yield 就相當于 return + 暫停,把 n 扔出去,并且停下來,不進行循環了,當你下次再用 next() 的時候,值再走到 while true里邊,進行下一次循環。 def func():n = 0while True:n += 1yield n g = func() print(next(g)) print(next(g)) print(next(g)) print(next(g)) >>> 1 2 3 4斐波那契數列:
def fib(length):a, b = 0, 1n = 0while n<length: # print(b)yield ba, b = b, a+bn += 1return '沒有更多元素!' g = fib(8) print(next(g)) print(next(g)) print(next(g)) print(next(g)) print(next(g)) print(next(g)) print(next(g)) print(next(g)) print(next(g)) print(next(g)) >>> 1 1 2 3 5 8 13 21 StopIteration: 沒有更多元素!生成器方法:
- next():獲取下一個元素
- send():像每次生成器中傳值的,第一次調用的時候必須先傳一個 None
生成器應用:
進程>線程>協程
一個進程可以用多個線程來并行完成,一個線程又可以用多個協程來并完成。
# 任務是前后進行的,先搬完磚才能聽歌 def task1(n):for i in range(n):print('正在搬第{}塊轉'.format(n))def task2(n):for i in range(n):print('正在聽第{}首歌'.format(n)) task1(3) task2(3) >>> 正在搬第0塊轉 正在搬第1塊轉 正在搬第2塊轉 正在聽第0首歌 正在聽第1首歌 正在聽第2首歌 # 兩個任務同時進行 def task1(n):for i in range(n):print('正在搬第{}塊轉'.format(i))yield None def task2(n):for i in range(n):print('正在聽第{}首歌'.format(i))yield None g1 = task1(3) g2 = task2(3) while True:try:g1.__next__()g2.__next__()except:break >>>正在搬第0塊轉 正在聽第0首歌 正在搬第1塊轉 正在聽第1首歌 正在搬第2塊轉 正在聽第2首歌生成器的構成:
- 通過列表推導式完成
- 通過 函數 + yield 完成
產生元素:
- next(generator)
- 生成器自己的方法
- generator._ next _(),產生完畢再次調用,會產生異常
- generator.send(),給生成器送值
生成器的應用:在協程中使用
七、迭代器
可迭代的對象:
- 生成器
- 元組、列表、集合、字典、字符串
如何判斷是否可迭代:isinstance()
from collections import Iterable # 列表是可迭代的 list1 = [1,2,3] isinstance(list1,Iterable) >>> True # 整型是不可迭代的 isinstance(1,Iterable) >>> False # 生成器是可迭代的 g = (x +1 for x in range(10)) isinstance(g,Iterable) >>> True迭代器:可以被 next() 函數調用并不斷返回下一個值的對象,稱為迭代器 iterator
- 迭代器是訪問集合元素的一種方式
- 迭代器是可以記住遍歷位置的對象,迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問結束
- 迭代器只能往前,不能后退
生成器:可迭代,也是迭代器(可以用 next() 方法)
列表:可迭代,但不是迭代器(不可以 next() 方法)
怎么把一個可迭代的對象變成迭代器:iter(obj)
list1 = [1,2,3] print(type(list1)) list1 = iter(list1) print(type(list1)) print(next(list1)) print(next(list1)) >>> <class 'list'> <class 'list_iterator'> 1 2生成器:為了節省內存,一個個拿到元素,生成的方式有兩種,一種是 列表生成式的方式,另一種是借助函數+yield方式。
迭代器:只要能夠調用 next得到下一個元素的,就叫迭代器
迭代器是一個大的范圍, 生成器是迭代器的一種,生成器也是迭代器。
列表/元組等不是一個迭代器,但也可以變成一個迭代器。
迭代器:
- 借助 iter() 轉換,可以得到
- 不借助,本身就是迭代器
總結
以上是生活随笔為你收集整理的【python 2】python 进阶的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 拉风的游戏名字有哪些
- 下一篇: 【python 3】 面向对象