一些關(guān)于自己學(xué)習(xí)Python的經(jīng)歷的內(nèi)容,遇到的問題和思考等,方便以后查詢和復(fù)習(xí)。
聲明:本人學(xué)習(xí)是在扇貝編程通過網(wǎng)絡(luò)學(xué)習(xí)的,相關(guān)的知識(shí)、案例來源于扇貝編程。如果使用請(qǐng)說明來源。
for循環(huán)和while循環(huán)辨別
相同點(diǎn):
它倆最大的相同點(diǎn)是都是循環(huán),且都有循環(huán)體和縮進(jìn)??s進(jìn)是 Python 中用來表示層級(jí)關(guān)系的,非常的重要,縮進(jìn)錯(cuò)誤會(huì)導(dǎo)致代碼運(yùn)行結(jié)果不符合預(yù)期甚至報(bào)錯(cuò),這里再強(qiáng)調(diào)一下。
不同點(diǎn):
它倆最大的不同點(diǎn)在于循環(huán)次數(shù)是否確定。我們?cè)賮砘貞浺幌聝煞N循環(huán)的停止條件:while 循環(huán) 是在條件不滿足時(shí)停止循環(huán)。for 循環(huán) 是遍歷完整個(gè)序列的元素就停止循環(huán)。
因此,while 循環(huán) 更適合循環(huán)次數(shù)不確定的情況,而 for 循環(huán) 更適合循環(huán)次數(shù)確定的情況。
Break和continue比較
相同:
break 和 continue 它倆都只能用于循環(huán)內(nèi),且都是用于跳過循環(huán)。
不同點(diǎn)
所以 break 和 continue 語句的區(qū)別就是:break 語句用于在特定條件下 結(jié)束循環(huán),continue 語句用于在特定條件下 跳過當(dāng)前循環(huán)體中的剩余語句,繼續(xù)進(jìn)行下一輪循環(huán)。
練習(xí):輸入密碼
小貝用循環(huán)寫了個(gè)密碼檢測器,總共有 3 次試錯(cuò)機(jī)會(huì)。但小貝發(fā)現(xiàn),不管輸入的密碼正確與否,都要輸 3 遍才行。正確的做法應(yīng)該在密碼正確時(shí)結(jié)束。你能幫小貝解決這個(gè)問題嗎?
i = 0
while i < 3:
? i = i + 1? #這個(gè)可以放在這里
? # input() 函數(shù)可以獲取用戶輸入的字符串
? password = input('請(qǐng)輸入密碼')
? i = i + 1? #這個(gè)也可以放在這里
? if password == '520':
? ? print('密碼正確')
? ? break
? ? i = i + 1? #這個(gè)不不不不可以放在這里,否則輸入不正確的時(shí)候,永遠(yuǎn)還有三次機(jī)會(huì),因?yàn)閕一直是等于0 ,這里的賦值,不會(huì)用到else中。
? else:
print('密碼錯(cuò)誤,你還有' + str(3-i) + '次機(jī)會(huì)')
zip()函數(shù)
zip() 函數(shù)和range()結(jié)合使用,可以同時(shí)遍歷多個(gè)列表。(range()和for循環(huán)也能一起使用,遍歷)
例子:
names = ["吳承恩", "羅貫中", "施耐庵", "曹雪芹"]
books = ["西游記", "三國演義", "水滸傳", "紅樓夢(mèng)"]
for name, book in zip(names, books):
? print(book + '的作者是' + name)
# 輸出:
# 西游記的作者是吳承恩
# 三國演義的作者是羅貫中
# 水滸傳的作者是施耐庵
# 紅樓夢(mèng)的作者是曹雪芹
zip()函數(shù)返回結(jié)果是元組,需要用list改成列表,列表的元素是元組。
names = ["吳承恩", "羅貫中", "施耐庵", "曹雪芹"]
books = ["西游記", "三國演義", "水滸傳", "紅樓夢(mèng)"]
name_and_book = zip(names, books)
print(list(name_and_book))
# 輸出:[('吳承恩', '西游記'), ('羅貫中', '三國演義'), ('施耐庵', '水滸傳'), ('曹雪芹', '紅樓夢(mèng)')]
通過 list() 函數(shù)轉(zhuǎn)換后可以看到,它里面的元素是一個(gè)個(gè)元組。name, book 這樣用逗號(hào)分隔開的寫法可以獲取到元組中對(duì)應(yīng)的元素。這里其實(shí)又解鎖了元組的一個(gè)新知識(shí),可以用逗號(hào)分隔開的變量獲取元組里的各個(gè)元素。
# 3 個(gè)元素也同樣可以
a, b, c = ('我', '愛', 'Python')
print('a =', a)
print('b =', b)
print('c =', c)
# 輸出:
# a = 我
# b = 愛
# c = Pytho
names = ["吳承恩", "羅貫中", "施耐庵", "曹雪芹", "小貝"]
books = ["西游記", "三國演義", "水滸傳", "紅樓夢(mèng)"]
for name, book in zip(names, books):
? print(book + '的作者是' + name)
# 輸出:
# 西游記的作者是吳承恩
# 三國演義的作者是羅貫中
# 水滸傳的作者是施耐庵
# 紅樓夢(mèng)的作者是曹雪芹
可以看到,老師只給 names 列表添加了一個(gè)元素,結(jié)果和之前還是一樣的。因此結(jié)論是:當(dāng)用 zip() 函數(shù)同時(shí)遍歷兩個(gè)列表時(shí),如果兩個(gè)列表長度不一樣,遍歷次數(shù)以長度短的列表長度為準(zhǔn)。
練習(xí):遍歷兩個(gè)列表
左青龍
右白虎
前朱雀
后玄武
directions = ['左', '右', '前', '后']
animals = ['青龍', '白虎', '朱雀', '玄武']
for direction, animal in zip(directions, animals):
? print(direction + animal)
最后一行改成,號(hào)連接的話,連個(gè)部分之間是有空格的。
Print(direction, animal) 結(jié)果是 左 青龍
enumerate() 函數(shù)
老師還想給你介紹一個(gè)和新的列表相關(guān)的函數(shù)——enumerate() 函數(shù)。
enumerate,這個(gè)單詞是“列舉、枚舉”的意思。enumerate() 函數(shù)的用法很簡單,它的作用是同時(shí)給出序列的元素索引和元素。你看完下面這個(gè)例子你就明白是什么意思了:
names = ["吳承恩", "羅貫中", "施耐庵", "曹雪芹"]
for index, item in enumerate(names):
? print(index, item)
# 輸出:
# 0 吳承恩
# 1 羅貫中
# 2 施耐庵
# 3 曹雪芹
可以看到,index 是列表中元素的索引,item 是列表中對(duì)應(yīng)的元素。寫法是不是和 zip() 函數(shù)結(jié)合的 for 循環(huán)很像?我想你應(yīng)該猜出 enumerate() 函數(shù)的返回值長啥樣了吧,我們來驗(yàn)證一下:
names = ["吳承恩", "羅貫中", "施耐庵", "曹雪芹"]
print(list(enumerate(names)))
# 輸出:[(0, '吳承恩'), (1, '羅貫中'), (2, '施耐庵'), (3, '曹雪芹')]
enumerate() 函數(shù)返回值是 enumerate 類型,zip() 函數(shù)返回值是 zip 類型,都需要用 list() 函數(shù)轉(zhuǎn)換
練習(xí):報(bào)數(shù)程序
在沒有學(xué) enumerate() 函數(shù)之前,小貝寫了一個(gè)報(bào)數(shù)的程序。現(xiàn)在你掌握了 enumerate() 函數(shù),快來幫小貝用 enumerate() 函數(shù)改進(jìn)一下代碼吧!
初始程序:
names = ['小貝', '聞聞', '幫主']
index = 1
for item in names:
? print(item + str(index))
? index += 1
修改之后
names = ['小貝', '聞聞', '幫主']
for index, item in enumerate(names): #最初把index寫在后面,結(jié)果報(bào)錯(cuò)了。因?yàn)榇蛴〉臅r(shí)候,索引是打印在后面的,所以我這里也寫在后面。
但是enumerate在提前列表的元素和索引時(shí),只能是索引在前,元素在后。
? print(item + str(index + 1))
練習(xí):密碼破解
網(wǎng)絡(luò)攻防聽上去很高端、很難懂,但有些概念其實(shí)很簡單。比如密碼破解,最簡單的方式就是暴力破解,也就是窮舉法。人工手動(dòng)地去一個(gè)一個(gè)試密碼既耗時(shí)又耗力,而這種事對(duì)計(jì)算機(jī)來說可是小菜一碟。
接下來,我們來寫一個(gè)簡單的密碼破解器。為了方便窮舉、快速破解密碼,我們規(guī)定密碼只有 4 位純數(shù)字。因此,只需要窮舉 1000-9999 之間的所有數(shù)字和密碼對(duì)比即可。
拓展:現(xiàn)實(shí)中的密碼更加復(fù)雜,破解起來也更耗時(shí)。而且軟件會(huì)限制你嘗試的次數(shù),所以暴力破解是密碼破解的下下策。
from random import randint
a = 9876
while True:
? number = randint(1000, 9999)? #和第一句要一起使用,不能只用第二句
? if number == a:? # 最初等號(hào)只寫了一個(gè),后面的冒號(hào)也忘記了
? ? break
print(number)
我的這個(gè)程序使用的是隨機(jī)生成一個(gè)四位數(shù),然后比對(duì),從而破解。
password = 2349
i = 1000
while i != password:
? i = i + 1
? if i == password:
? ? break? ? ? ? ? # 這兩個(gè)可以去掉,因?yàn)閕不等于密碼的時(shí)候,才循環(huán),否則就退出循環(huán),打印i,所以這里不需要跳出循環(huán)的語句。
print(i)
password = 2349
i = 1000? ? ? #這個(gè)初始值也不需要,因?yàn)閞ange()會(huì)遍歷范圍內(nèi)的每個(gè)值,這個(gè)就不需要
for i in range(1000, 9999):
? i = i + 1? #這個(gè)也可以不要,因?yàn)槭潜闅v每個(gè)數(shù)字,然后比對(duì)的,所以不需要慢慢增加
? if i == password:
? ? break
print(i)
