# 幾個好玩有趣的Python入門例項

• `turtle`庫開始自己的繪畫
• 寫一個屬於自己的文字進度條
• 蒙特卡洛方法計算π
• 分形幾何，Koch雪花曲線
• 輸入一組資料，進行簡單的統計
• 小說詞頻統計，統計三國演義中誰出場率最高
• 輕鬆抓住文字主旨：文字詞雲生成

# drawing with turtle

``````from turtle import *
color('red', 'yellow')
begin_fill()
while True:
forward(200)
left(170)
if abs(pos()) < 1:
break
end_fill()
done()``````

``````import turtle as t
# size傳入最大的圓的半徑
def draw_Star(size):
t.setup(1200, 1000)
t.speed(11)
t.pensize(2)
t.pencolor('grey')
for r, pen_size in [(size//7, 3), (size*6//7, 4), (size, 4)]:
t.penup()
t.goto(0, -r)
t.pendown()
t.pensize(pen_size)
t.circle(r)
t.penup()
t.goto(0, 0)
r = size * 5.5 // 7
for i in range(6):
t.pendown()
t.pensize(3)
t.seth(i * 60   30)
t.fd(r)
t.goto(0, 0)
t.goto(0, r)
t.seth(-150)
t.pensize(5)
for i in range(6):
t.fd(r)
t.left(60)
r = r - size // 50
t.goto(0, r)
t.pensize(10)
t.seth(-120)
t.pencolor('orange')
for i in range(3):
t.fd(r * (3**0.5))
t.left(120)
t.penup()
t.goto(0, 0)
t.seth(30)
t.fd(r)
t.seth(-180)
t.pendown()
for i in range(3):
t.fd(r * (3 ** 0.5))
t.left(120)
t.hideturtle()
t.done()
draw_Star(400)``````

# 文字進度條

``````import time
def bar(scale):
print('===========執行開始============')
for i in range(scale   1):
a = '*' * i
b = '.' * (scale - i)
c = (i / scale) * 100
print('\r{:^3.0f}%[{}->{}]'.format(c, a, b), end = '')
time.sleep(0.05)
print('\n===========執行結束============')``````

``````import time
def pro_bar(scale):
print('執行開始'.center(scale // 2, '='))
start = time.perf_counter()
for i in range(scale   1):
a = '*' * i
b = '.' * (scale - i)
c = (i / scale) * 100
dur = time.perf_counter() - start
print('\r{:^3.0f}%[{}->{}] {:.2f}s'.format(c, a, b, dur), end = '')
time.sleep(0.05)
print('\n'   '執行結束'.center(scale // 2, '='))
pro_bar(50)``````

# 蒙特卡洛方法計算π

``````from random import random
from time import perf_counter
def calPI(N = 100):
hits = 0
start = perf_counter()
for i in range(1, N*N 1):
x, y = random(), random()
dist = pow(x ** 2   y ** 2, 0.5)
if dist <= 1.0:
hits  = 1
pi = (hits * 4) / (N * N)
use_time = perf_counter() - start
return pi, use_time
PI, use_time = calPI(1000)
print('\nuse Monte Carlo method to calculate PI: {}'.format(PI))
print('use time: {} s'.format(use_time))``````

# 遞迴繪製Koch雪花曲線

koch雪花曲線分形幾何中的一個經典曲線。

``````import turtle
def koch(size, n):
if n == 0:
turtle.fd(size)
else:
for angle in [0, 60, -120, 60]:
turtle.left(angle)
koch(size/3, n-1)
def main():
turtle.setup(1200, 1000)
turtle.speed(11)
turtle.penup()
turtle.goto(-300, 200)
turtle.pendown()
turtle.pensize(2)
level = 4
koch(600, level)  # 3階科赫曲線
turtle.right(120)
koch(600, level)
turtle.right(120)
koch(600, level)
turtle.hideturtle()
turtle.done()
main()``````

`level`為4的Koch雪花如下：

Koch曲線形成過程（來自Matrix67）：

# 簡單統計

``````# -*- coding: utf-8 -*-
# 輸入資料
def getNum():
nums = []
iNumStr = input('please input a sequence of numbers (enter to exit): ')
while iNumStr != '':
nums.append(eval(iNumStr))
iNumStr = input('please input a sequence of numbers (enter to exit): ')
return nums
# 平均數
def average(numbers):
return sum(numbers) / len(numbers)
# 標準差
def dev(numbers, average):
sdev = 0.0
for num in numbers:
sdev  = (num - average) ** 2
return pow(sdev / len(numbers), 0.5)
# 中位數
def median(numbers):
sorted(numbers)
size = len(numbers)
if size % 2 == 0:
return (numbers[size//2-1]   numbers[size//2]) / 2
else:
return numbers[size//2]
# 絕對與相對誤差
def rel_dev(numbers, average):
_max = max(abs(max(numbers) - average), abs(min(numbers) - average))
return _max, _max / average
def main():
nums = getNum()
if len(nums) == 0:
print('no data')
else:
ave = average(nums)
devs = rel_dev(nums, ave)
print('和:{:.4f},平均數:{:.4f},中位數:{:.4f},方差:{:.4f},絕對誤差:{:4f},相對誤差:{:.4f}' \
.format(sum(nums), ave, median(nums), dev(nums, ave), devs[0], devs[1]))
if __name__ == '__main__':
main()``````

# 小說詞頻統計

• 中文小說：使用第三方庫`jieba`切分，統計
• 英文小說：去掉特殊干擾字元，直接切分為單詞，遍歷統計

``````def getText():
txt = open('novels/hamlet.txt', 'r').read()
txt = txt.lower()   # 去掉大小寫干擾
# 去掉特殊符號干擾
for ch in '!"#\$%&()* ,-./:;<=>[email protected][\\]^_`{|}~\'':
txt = txt.replace(ch, ' ')
return txt
hamletTxt = getText()
words = hamletTxt.split()
counts = {}
for word in words:
counts[word] = counts.get(word, 0)   1
items = list(counts.items())
# 將其按照詞出現數量按照降序排列
items.sort(key = lambda x : x[1], reverse = True)
for i in range(20):
word, count = items[i]
print('{:^10}{:^10}'.format(word, count))``````

``````import jieba
def getWords():
txt = open('novels/threekingdoms.txt', 'r', encoding = 'utf-8').read()
words = jieba.lcut(txt)
counts = {}
for word in words:
if len(word) == 1:
continue
else:
counts[word] = counts.get(word, 0)   1
word_list = list(counts.items())
word_list.sort(key = lambda x : x[1], reverse = True)
return word_list``````

``````import jieba
def countWords(excludes, merges):
txt = open('novels/threekingdoms.txt', 'r', encoding = 'utf-8').read()
words = jieba.lcut(txt)
counts = {}
# 取出長度為一的詞和符號以及excludes中的詞
for word in words:
if len(word) == 1 or word in excludes:
continue
else:
counts[word] = counts.get(word, 0)   1
# 合併名稱相同的人名
for merge in merges:
for name in merge[1]:
counts[merge[0]]  = counts.get(name, 0)
del counts[name]
word_list = list(counts.items())
word_list.sort(key = lambda x : x[1], reverse = True)
return word_list
excludes = {'卻說','二人','不可','主公','陛下','漢中','只見','眾將','後主','蜀兵','上馬','大叫','太守','此人','夫人',
'先主','後人','背後','城中','天子','一面','何不','大軍','忽報','先生','百姓','何故','不能','如此','如何',
'然後','先鋒','不如','趕來','原來','令人','江東','下馬','喊聲','正是','徐州','忽然','荊州','左右','軍馬',
'因此','成都','不見','未知','大敗','大事','之後','一軍','引軍','起兵','軍中','接應','引兵','次日','大喜',
'進兵','大驚','可以','以為','大怒','不得','心中','下文','一聲','追趕','糧草','天下','東吳','於是','都督',
'曹兵','一齊','分解','回報','分付','只得','出馬','三千','大將','許都','隨後','報知','今日','不敢','魏兵',
'前面','之兵','且說','眾官','洛陽','領兵','商議','軍士','星夜','精兵','城上','之計','不肯','相見','其言',
'一日','而行','文武','襄陽','準備','若何','出戰','親自','必有','一人','人馬','不知','何人','此事','之中',
'伏兵','祁山','乘勢','忽見','大笑','樊城','兄弟','首級','立於','西川','傳令','當先','五百','一彪','堅守',
'此時','之間','投降','五千','埋伏','長安','三路','遣使','將軍','關興','軍師','朝廷','三軍','大王','回見',
'大將軍','必然','將士','是夜','小路' }
merges = [  ('劉備',('玄德','玄德曰','玄德問','劉玄德','玄德大','玄德自','玄德聞','皇叔','劉皇叔')),
('關羽',('關公','雲長','關雲長')),
('孔明',('諸葛亮','孔明曰','孔明笑','孔明之','孔明自')),
('曹操',('丞相','孟德','曹公','曹孟德')),
('張飛',('翼德','張翼德'))
]
word_list = countWords(excludes, merges)
for i in range(30):
word, count = word_list[i]
print('{0:^10}{1:{3}^10}{2:^15}'.format(i 1, word, count, chr(12288))) # chr(12288)為中文空格``````

``````    1     　　　　劉備　　　　     1578
2     　　　　曹操　　　　     1485
3     　　　　孔明　　　　     1485
4     　　　　關羽　　　　      820
5     　　　　張飛　　　　      393
6     　　　　呂布　　　　      300
7     　　　　趙雲　　　　      278
8     　　　　孫權　　　　      264
9     　　　 司馬懿　　　　     221
10    　　　　周瑜　　　　      217
11    　　　　袁紹　　　　      191
12    　　　　馬超　　　　      185
13    　　　　魏延　　　　      180
14    　　　　黃忠　　　　      168
15    　　　　姜維　　　　      151
16    　　　　馬岱　　　　      127
17    　　　　龐德　　　　      122
18    　　　　孟獲　　　　      122
19    　　　　劉表　　　　      120
20    　　　 夏侯惇　　　　     116
21    　　　　董卓　　　　      114
22    　　　　孫策　　　　      108
23    　　　　魯肅　　　　      107
24    　　　　徐晃　　　　      97
25    　　 　司馬昭　　　　     89
26    　　 　夏侯淵　　　　     88
27    　　　　王平　　　　      88
28    　　　　劉璋　　　　      85
29    　　　　袁術　　　　      84
30    　　　　呂蒙　　　　      83``````

To be continued …