本章通過模擬擲骰子計算的5案例來進行學(xué)習(xí)基礎(chǔ)的Python程序
案例描述
通過計算機程序模擬拋擲骰子,并顯示各點數(shù)的出現(xiàn)次數(shù)及頻率
比如:拋擲2個骰子50次,出現(xiàn)點數(shù)為7的次數(shù)是8,頻率是0.16

案例分析
根據(jù)以下函數(shù)判斷密碼強度并輸出:
1.設(shè)置一個變量strength_level用于記錄密碼的強度,初始為0。滿足一個條件,對其加1;
2.長度判斷:使用len()方法;
3.包含數(shù)字判斷:對密碼字符串遍歷,使用isnumeric()方法;
4.包含字母判斷:對密碼字符串遍歷,使用isalpha()方法;
5.如果strength_level等于3,密碼強度合格,否則不合格
v1.0
新建一個簡單的Python程序,1.0功能:模擬拋擲1個骰子,并輸出其結(jié)果;通過Python的random模塊模擬隨機事件或者生成隨機數(shù);遍歷列表時,使用enumerate()函數(shù)同時獲取每個元素的索引號及其元素值。首先擲骰子編寫成一個函數(shù),然后編寫主函數(shù)設(shè)置參數(shù)并開始擲骰子,最后輸出結(jié)果。
知識點:
1.random模塊
(1)random模塊用于生成隨機數(shù),包含整數(shù),浮點數(shù),獲取列表中的隨機元素
(2)常用函數(shù),random庫里面有幾個常用的函數(shù),分別如下:

2.enumerate()函數(shù)
(1)enumerate()函數(shù)用于將可遍歷的組合轉(zhuǎn)換為一個索引序列
(2)一般用于for循環(huán)中,同時列出元素和元素的索引號
random模塊函數(shù)示例:

enumerate函數(shù)示例:

PS:更多random模塊的方法請參考:https://docs.python.org/3/library/random.html
扔骰子函數(shù),先引入ramdom庫,randint(1,6)返回的是1 - 6的整數(shù)賦值給dice_num,最后返回該結(jié)果:
import random
def roll_dice():
"""
擲骰子
"""
dice_num = random.randint(1, 6)
return dice_num
主體代碼,里面先初始化主要的參數(shù)是total_time次數(shù)和result_list次數(shù)統(tǒng)計列表,for循環(huán)迭代range(total_times)對象,計算每次擲骰子的結(jié)果然后再for循環(huán)給統(tǒng)計列表計數(shù),若符合則+1,最后enumerate()會返回兩個參數(shù),第1個給i,第2個給result再進行for循環(huán)迭代,因為列表下標(biāo)是從0開始的,所以format的i需要+1正確顯示0:
# 擲骰子次數(shù)
total_times = 1000
# 初始化結(jié)果列表[0,0,0,0,0,0]
result_list = [0] * 6
# 開始擲骰子
for i in range(total_times):
roll = roll_dice()
# 給列表計數(shù)
for j in range(1, 7):
if roll == j:
result_list[j - 1] += 1
# 輸出結(jié)果
for i, result in enumerate(result_list):
print("計數(shù)為{}的骰子出現(xiàn)次數(shù){},頻率:{}".format(i + 1, result, result / total_times))
結(jié)果如圖所示:

v2.0
在v1.0的基礎(chǔ)上,2.0功能:模擬拋擲2個骰子,并輸出其結(jié)果。由于要2個骰子,因此骰子的點數(shù)要新建列表,然后使用字典將對應(yīng)的點數(shù)和次數(shù)關(guān)聯(lián)起來。zip()函數(shù)的作用就是把骰子列表和統(tǒng)計列表組合成元組,然后用dict()轉(zhuǎn)換成字典。
知識點:
1.zip()函數(shù):
(1)zip()函數(shù)用于將對應(yīng)的元素打包成一個個元組
(2)注意:元組中的元素是不可修改的,若要修改元素值可轉(zhuǎn)換成字典類型;如:dict(zip(l1, l2))
(3)Python2.x版本和Python3版本的zip()函數(shù)返回結(jié)果不同,示例如下:


zip函數(shù)示例:

投擲子函數(shù)之前相同,不展示了。
具體代碼,首先新建結(jié)果列表,因為2個骰子的結(jié)果有11種,所以要[0]*11,而點數(shù)列表對應(yīng)也有11種,并且是2 - 12。dict(zip(roll_list, result_list))返回的結(jié)果是key為點數(shù),value為結(jié)果計數(shù)的字典:
# 擲骰子次數(shù)
total_times = 1000
# 初始化結(jié)果列表[0,0,0,0,0,0]
result_list = [0] * 11
# 初始化點數(shù)列表
roll_list = list(range(2, 13))
roll_dict = dict(zip(roll_list, result_list))
print(roll_dict)
# 開始擲骰子
for i in range(total_times):
roll1 = roll_dice()
roll2 = roll_dice()
# 給列表計數(shù)
for j in range(2, 13):
if (roll1 + roll2) == j:
roll_dict[j] += 1
# 輸出結(jié)果
for i, result in roll_dict.items():
print("計數(shù)為{}出現(xiàn)的次數(shù)為{},頻率:{}".format(i, result, result / total_times))
運行結(jié)果:
v3.0
在2.0的基礎(chǔ)上,3.0功能:可視化拋擲2個骰子的結(jié)果;通過繪制散點圖圖像,簡單分析數(shù)據(jù)的分布情況,使用到matploylib庫。
知識點:
1.Python數(shù)據(jù)可視化:matplotlib模塊
(1)matplotlib是一個數(shù)據(jù)可視化函數(shù)庫
(2)matplotlib的子模塊pyplot提供了2D圖表制作的基本函數(shù)
(3)例子:https://matplotlib.org/gallery.html
(4)散點圖繪制操作
import matplotlib.pyplot as plt
plt.scatter(x, y) # x, y分別是x坐標(biāo)和y坐標(biāo)的列表
plt.show()

2.scatter()參數(shù)詳解
matplotlib.pyplot.scatter(x, y, s=None, c=None, marker=None, cmap=None, norm=None, vmin=None, vmax=None, alpha=None, linewidths=None, verts=None, edgecolors=None, *, data=None, **kwargs)
參數(shù)的解釋:
x,y:表示的是大小為(n,)的數(shù)組,也就是我們即將繪制散點圖的數(shù)據(jù)點
s:是一個實數(shù)或者是一個數(shù)組大小為(n,),這個是一個可選的參數(shù)。
c:表示的是顏色,也是一個可選項。默認是藍色'b',表示的是標(biāo)記的顏色,或者可以是一個表示顏色的字符,或者是一個長度為n的表示顏色的序列等等,感覺還沒用到過現(xiàn)在不解釋了。但是c不可以是一個單獨的RGB數(shù)字,也不可以是一個RGBA的序列??梢允撬麄兊?維數(shù)組(只有一行)。
marker:表示的是標(biāo)記的樣式,默認的是'o'。
cmap:Colormap實體或者是一個colormap的名字,cmap僅僅當(dāng)c是一個浮點數(shù)數(shù)組的時候才使用。如果沒有申明就是image.cmap
norm:Normalize實體來將數(shù)據(jù)亮度轉(zhuǎn)化到0-1之間,也是只有c是一個浮點數(shù)的數(shù)組的時候才使用。如果沒有申明,就是默認為colors.Normalize。
vmin,vmax:實數(shù),當(dāng)norm存在的時候忽略。用來進行亮度數(shù)據(jù)的歸一化。
alpha:實數(shù),0-1之間。
主要代碼,骰子的計數(shù)方式和之前相同,新增繪制散點圖。散點圖繪制要先import引入庫,在用scatter()設(shè)置骰子1和2的顯示方式,參數(shù)包含x軸坐標(biāo),y軸坐標(biāo),顏色和透明度,最后顯示:
# 擲骰子次數(shù)
total_times = 1000
# 初始化結(jié)果列表[0,0,0,0,0,0]
result_list = [0] * 11
# 初始化點數(shù)列表
roll_list = list(range(2, 13))
roll_dict = dict(zip(roll_list, result_list))
# 初始化骰子結(jié)果列表
roll1_result = []
roll2_result = []
# 開始擲骰子
for i in range(total_times):
roll1 = roll_dice()
roll2 = roll_dice()
roll1_result.append(roll1)
roll2_result.append(roll2)
# 給列表計數(shù)
for j in range(2, 13):
if (roll1 + roll2) == j:
roll_dict[j] += 1
# 輸出結(jié)果
for i, result in roll_dict.items():
print("計數(shù)為{}出現(xiàn)的次數(shù)為{},頻率:{}".format(i, result, result / total_times))
# 繪制散點圖
x = range(1, total_times + 1)
plt.scatter(x, roll1_result, c="red", alpha=0.5)
plt.scatter(x, roll2_result, c="blue", alpha=0.5)
plt.show()
代碼部分運行結(jié)果:

v4.0
在v3.0的基礎(chǔ)上,4.0功能:對結(jié)果進行簡單的數(shù)據(jù)統(tǒng)計和分析。使用matplotlib直方圖做簡單的數(shù)據(jù)統(tǒng)計分析。直方圖可以直接看到分布情況,簡單易懂。在做數(shù)據(jù)分析或機器學(xué)習(xí)時會經(jīng)常用到。
知識點:
1.matplotlib直方圖
(1)直方圖是一種對數(shù)據(jù)分布情況的圖形表示
(2)首先要對數(shù)據(jù)進行分組,然后統(tǒng)計每個分組內(nèi)數(shù)據(jù)的數(shù)量。
(3)作用:
? 顯示各分組頻率或數(shù)量分布的情況
? 易于顯示各組之間頻率或數(shù)量的差別
(4)matplotlib繪制直方圖
plt.hist(data, bins)
data: 數(shù)據(jù)列表
bins: 分組邊界
2.hist()參數(shù)和返回值:
調(diào)用方式:
n, bins, patches = plt.hist(arr, bins=10, normed=0, facecolor='black', edgecolor='black',alpha=1,histtype='bar')
hist的參數(shù)非常多,但常用的就這六個,只有第一個是必須的,后面四個可選
arr: 需要計算直方圖的一維數(shù)組
bins: 直方圖的柱數(shù),可選項,默認為10
normed: 是否將得到的直方圖向量歸一化。默認為0
facecolor: 直方圖顏色
edgecolor: 直方圖邊框顏色
alpha: 透明度
histtype: 直方圖類型,‘bar’, ‘barstacked’, ‘step’, ‘stepfilled’
返回值 :
n: 直方圖向量,是否歸一化由參數(shù)normed設(shè)定
bins: 返回各個bin的區(qū)間范圍
patches: 返回每個bin里面包含的數(shù)據(jù),是一個list
hist()函數(shù)參數(shù)詳解:https://matplotlib.org/api/_as_gen/matplotlib.pyplot.hist.html
https://blog.csdn.net/qq_41940950/article/details/82937966
3.hist示例和中文顯示錯誤解決方法



plt.rcParams[]詳解參考:http://www.cnblogs.com/pacino12134/p/9776882.html
主要代碼,骰子的計數(shù)方式和之前相同,新增繪制直方圖。直方圖繪制要先import引入庫,在用hist()設(shè)置直方圖的顯示形狀,參數(shù)包含x軸坐標(biāo),y軸坐標(biāo),歸一化即y軸數(shù)據(jù)修改為頻率,邊框顏色(間隔開方便觀察);title()設(shè)置直方圖標(biāo)題,xlabel()設(shè)置x軸標(biāo)題,ylabel設(shè)置y軸標(biāo)題,這3個都用size更改字體大小。最后顯示::
# 擲骰子次數(shù)
total_times = 100000
# 初始化結(jié)果列表[0,0,0,0,0,0]
result_list = [0] * 11
# 初始化點數(shù)列表
roll_list = list(range(2, 13))
roll_dict = dict(zip(roll_list, result_list))
# 擲骰子結(jié)果初始化
roll_list = []
# 開始擲骰子
for i in range(total_times):
roll1 = roll_dice()
roll2 = roll_dice()
roll_list.append(roll1 + roll2)
# 給列表計數(shù)
for j in range(2, 13):
if (roll1 + roll2) == j:
roll_dict[j] += 1
# 輸出結(jié)果
for i, result in roll_dict.items():
print("計數(shù)為{}出現(xiàn)的次數(shù)為{},頻率:{}".format(i, result, result / total_times))
# 繪制散點圖
plt.hist(roll_list, bins=range(2, 14), density=1, edgecolor="yellow", rwidth=3) # normed=1
plt.title("骰子點數(shù)統(tǒng)計",size=16)
plt.xlabel("點數(shù)", size=10)
plt.ylabel("頻率", size=10)
plt.show()
執(zhí)行結(jié)果:

v5.0
在v4.0的基礎(chǔ)上,5.0功能:使用科學(xué)計算庫簡化程序,完善數(shù)據(jù)可視化結(jié)果。使用科學(xué)計算庫NumPy簡化程序。numpy可以直接生成大量的隨機數(shù)對象數(shù)組,不需要再每次生成1個再加入列表中了,除此之外numpy還包含其他處理多維數(shù)組的方法。
知識點:
- NumPy
(1)NumPy (Numeric Python):用Python實現(xiàn)的科學(xué)計算庫
(2)包括:
a.強大的N維數(shù)組對象array
b.成熟的科學(xué)函數(shù)庫
c.實用的線性代數(shù)、隨機數(shù)生成函數(shù)等
(3)NumPy的操作對象是多維數(shù)組ndarray
(4)ndarray.shape 數(shù)組的維度;操作方法如下:
創(chuàng)建數(shù)組:np.array(<list>),np.arrange() …
改變數(shù)組形狀 reshape()
2.histogram()詳解
umpy.histogram(a, bins=10, range=None, normed=False, weights=None, density=None)
參數(shù):
a : array_like
輸入數(shù)據(jù)。直方圖在平頂陣列上計算。
bin : int或scalars或str的序列,可選
如果bin是int,則它定義給定范圍內(nèi)的等寬bin的數(shù)量(默認為10)。如果bin是一個序列,它定義了一個單調(diào)增加的bin邊緣數(shù)組,包括最右邊的邊,允許不均勻的bin寬度。
range :( float,float),可選
箱子的下部和上部范圍。如果沒有提供,范圍很簡單。超出范圍的值將被忽略。范圍的第一個元素必須小于或等于第二個元素。range也會影響自動bin計算。雖然基于范圍內(nèi)的實際數(shù)據(jù)計算箱寬度是最佳的,但箱計數(shù)將填充整個范圍,包括不包含數(shù)據(jù)的部分。(a.min(), a.max())
normed : bool,可選
從版本1.6.0開始不推薦使用。
這相當(dāng)于density參數(shù),但是對于不相等的bin寬度產(chǎn)生不正確的結(jié)果。不應(yīng)該使用它。
weights : array_like,可選
一系列重量,形狀與a相同。中的每個值 一個不僅有助于其相關(guān)聯(lián)的權(quán)重對所述的箱數(shù)(而不是1)。如果密度為True,則將權(quán)重歸一化,以使密度在整個范圍內(nèi)的積分保持為1。
density : bool,可選
如果False,結(jié)果將包含每個bin中的樣本數(shù)。如果True,結(jié)果是bin處的概率密度函數(shù)的值,則歸一化使得該范圍上的積分為1.注意,除非選擇單位寬度的區(qū)間,否則直方圖值的總和將不等于1; 它不是概率質(zhì)量函數(shù)。
返回值,有兩個,
hist : array
bin_edges : array of dtype float,bin edges 的長度要是 hist 的長度加1,bin edges (length(hist)+1),也即 (bin_edges[0], bin_edges[1]) ? hist[0],….,(bin_edges[-2], bin_edges[-1]) ? hist[-1],bin_edges 參數(shù)與輸入?yún)?shù)的 bins 保持一致;
PS:numpy詳細教程參考:https://blog.csdn.net/a373595475/article/details/79580734
數(shù)組維度詳解:https://www.cnblogs.com/Allen-rg/p/9592590.html
np.arange()函數(shù)詳解:https://jingyan.baidu.com/article/e6c8503c1e89d6e54f1a188c.html
reshape()函數(shù)詳解:https://blog.csdn.net/qq_28618765/article/details/78083895
數(shù)組的使用:http://www.cnblogs.com/dwnblogs/archive/2012/07/15/2592714.html
histogram()詳解參考:https://docs.scipy.org/doc/numpy/reference/generated/numpy.histogram.html
主函數(shù)代碼,先導(dǎo)入numpy庫,調(diào)用里面的random.randint()直接生成含有大量隨機數(shù)的對象數(shù)組,方法函數(shù)包含起始數(shù),終結(jié)數(shù),數(shù)據(jù)數(shù)量;然后調(diào)用np.histogram統(tǒng)計結(jié)果,返回2-12點數(shù)的出現(xiàn)次數(shù)和對應(yīng)的區(qū)間;然后hist繪制直方圖,參數(shù)包含y軸數(shù)據(jù),x軸數(shù)據(jù),歸一化,邊框顏色,邊框?qū)挾龋綏l間隔;xticks()設(shè)置x軸坐標(biāo)點的顯示,參數(shù)包含顯示坐標(biāo)(這里+0.5居中顯示方便觀看)和坐標(biāo)點顯示的標(biāo)題;接著設(shè)置標(biāo)題,y和x的標(biāo)題,最后顯示。
# 擲骰子次數(shù)
total_times = 1000000
# 使用array操作隨機數(shù)
roll1_arr = np.random.randint(1, 7, size=total_times)
roll2_arr = np.random.randint(1, 7, size=total_times)
# 統(tǒng)計結(jié)果、
result_arr = (roll1_arr + roll2_arr)
hist, bins = np.histogram(result_arr, bins=range(2, 14))
print(hist)
print(bins)
# 繪制散點圖
plt.hist(result_arr, bins=range(2, 14), density=1, edgecolor="yellow", linewidth=1, rwidth=0.8) # normed=1
# 設(shè)置x軸坐標(biāo)點顯示
tick_labels = ["2點", "3點", "4點", "5點",
"6點", "7點", "8點", "9點", "10點", "11點", "12點"]
tick_pos = np.arange(2, 13) + 0.5
plt.xticks(tick_pos, tick_labels)
plt.title("骰子點數(shù)統(tǒng)計", size=16)
plt.xlabel("點數(shù)", size=10)
plt.ylabel("頻率", size=10)
plt.show()
執(zhí)行結(jié)果:


總結(jié)
模擬擲骰子的5個例子,知識點歸納如下:

重點是Numpy庫的知識點和相關(guān)操作和matplotlib庫的操作
完整代碼查看碼云