---
title: python讀書會(六)
tags: python讀書會
notes: 爬蟲、神經網路、DL、%d、字串的速度文檔、比較速度實驗、unicode、輸入字元、array、作圖...
---
{%hackmd @themes/orangeheart %}
## 6.0 回顧...
1. 模組: math, random, python內建函數(這個還沒完成,請替我完成它,順便熟悉一下這些功能)...
2. 介紹tuple、list和set的特性
3. 刷題(虧數、盈數、完全數)
:::info
:bird:**complement**
list還有以下這些寫法 :
```python
list1 = [2 ** x for x in range(10) if x > 5]
list2 = [x + y for x in ['Python ', 'C '] for y in ['Language', 'Programming']]
```
:::
## 6.1 數據類型
#### 6.1.1 set
set當中的資料是無序的,也就是說,你無法利用位置索引去找到其中的元素。
set裡面可以有tuple,卻不允許有list,~~而且抗議無效~~。
- [ ] 程式碼 6.1.1a
```python=
set1 = {1,2,3,4,5}
set2 = {5,5,5,5,5,5,1,4,3,4,2,1}
print(set1 == set2)
```
- [ ] 程式碼 6.1.1b
```python=
#add:加入一個元素
#update:加入多個元素
set3 = {1,3}
set3.add("Hello, world!")
print(set3)
set3.update([(3, 2, chr(88)), 3, True])
print(set3)
set3.update([4, 5], {1, 6, 8})
print(set3)
```
- [ ] 程式碼 6.1.1c
```python=
#有幾種移除set元素的函數,他們的差異如下:
set4 = {1, 3, 4, 5, 6}
print(set4)
set4.discard(4)
print(set4)
set4.remove(6)
print(set4)
set4.discard(2)
print(set4)
set4.remove(2)#會error
###############我是分隔線###############
set5 = set("HelloWorld")#將文字弄成集合會有不可思議的效果
print(set5)
print(set5.pop())#隨機刪除一個物件,因為set沒有索引
set5.pop()
print(set5)
set5.clear()#全部刪掉
print(set5)
```
你可以將set想成是數學裡面的集合,在python中運用下列符號來表示聯集(union)、交集(intersection)、差集(difference)、對稱差集(symmetric difference)。

- [ ] 程式碼 6.1.1d
```python=
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}
#Union
print(A | B)#記住這個符號,shift+[Enter上面那個鍵]
print(A.union(B))#這樣表示也可以
#Intersection
print(A & B)
print(A.intersection(B))
#Difference
print(A - B)
print(A.difference(B))
#Symmetric Difference
print(A ^ B)
print(A.symmetric_difference(B))
```
- [ ] 程式碼 6.1.1e
```python=
#set.fn()才有效喔
add()
update()
clear()
difference()
discard()
intersection()
pop()
remove()
symmetric_difference()
union()
copy()
difference_update()
intersection_update()
isdisjoint()
issubset()
issuperset()
symmetric_difference_update()
##############我是分隔線#############
all()
any()
enumerate()
len()
max()
min()
sorted()#回傳一個list!!
sum()
```
在迭代中,除了range()、list、string以外,其實也可以使用set來進行迴圈。
```python
for letter in set("apple"):
print(letter)
```
數據型態中,我們有可變列表(list),也有不可變列表(tuple),還有可變集合(set),其實有個新的**不可變集合(frozenset)**,可以嘗試玩玩看。
##### 6.1.2 dictionary
Dictionary型態的數據長這樣: ```dict = {key1:value1, key2:value2, key3:value3}```
- [ ] 程式碼 6.1.2a
```python=
#也可以嘗試以這樣的方式創建dictionary
my_dict = dict([(1,'apple'), (2,'ball')])
print(my_dict)
```
當你創建一個```{}```時,回傳給電腦的資料類型會是```dictionary```,而不是```set```。
- [ ] 程式碼 6.1.2b
```python=
a = {}
print(type(a))
```
要從dict型態數據中提取資料只能輸入```key```以獲得```value```,```key```就像list的index,```value```則像是list的data。
- [ ] 程式碼 6.1.2c
```python=
# get vs [] for retrieving elements
dict1 = {'name': 'Jack', 'age': 26}
print(dict1.get('name'))
print(dict1['name'])#[]和.get()幾乎相同
print(dict1.get('Jack'))
print(dict1['Jack'])#.get()只會回傳None,但[]容易error
```
- [ ] 程式碼 6.1.2d
```python=
#更改dict資料
dict1['age'] = 27#修改
print(dict1)
dict1['address'] = 'Downtown'#新增
print(dict1)
########################################
squares = {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
print(squares.pop(4))#.pop(key),這邊會回傳value
print(squares)
print(squares.popitem())#隨機刪除一個
print(squares)
squares.clear()#所有資料都刪除
print(squares)
del squares#error
print(squares)
```
- [ ] 程式碼 6.1.2e
```python=
clear()
copy()
fromkeys(seq[, v])
get(key[,d])
items()
keys()
pop(key[,d])
popitem()
setdefault(key[,d])
update([other])
values()
```
- [ ] 程式碼 6.1.2f
```python=
score = {}.fromkeys(['Math', 'English', 'Science'], 0)
print(score)
for item in score.items():
print(item)#在用程式執行之前,先想想看會輸出什麼
print(list(sorted(score.keys())))#在用程式執行之前,先想想看會輸出什麼
```
**進階一點的~:fire:**
以下這些程式碼的技巧,可以嘗試用在list、tuple、set上,如果想要更加理解這些嵌套循環,可以查詢"dictionary comprehension"來獲得所求資源。
- [ ] 程式碼 6.1.2g
```python=
#❤️進階一點的
odd_squares = {x: x*x for x in range(11) if x % 2 == 1} #更輕鬆創建dict
print(odd_squares)
#✨再進階一點的
dictionary = {k1: {k2: k1 * k2 for k2 in range(1, 6)} for k1 in range(2, 5)}
print(dictionary)
```
## 6.2 Numpy, Matplotlib
第一件事情,請檢查一下你的電腦python有沒有numpy、matplotlib套件。
如果沒有,那就先去cmd上面```pip install numpy ^ pip install matplotlib```。
**[Numpy](https://numpy.org/)** 適用於操作有關陣列(array)、矩陣(matrix, matrices)的運算;比如說向量(vector)、線性代數(linear algebra)、傅立葉轉換(Fourier transforms)...。在處理數據時,它可以比list快50倍,因為資料是被連續儲存的,編寫語言部分是用 Python 編寫的,但大多數需要快速計算的部分是用C或C++編寫的(C語言學起來!!)。

**[Matplotlib](https://matplotlib.org/)** 用於在Python中創建靜態、動畫和交互式可視化,搭配numpy使用,效果相得益彰。

#### 6.2.1 Numpy.Array
現在就可以將之前學過的有關python的指令拿出來舉一反三!!
- [ ] 程式碼 6.2.1a
```python=
import numpy
arr = numpy.array([1, 2, 3, 4, 5])#list型態的數組,改成tuple和set試試看
print(arr)
print(type(arr))
```
**array維度:** 嵌套陣列(nested array),陣列裡面還有陣列,以下可以創建高維度陣列。

- [ ] 程式碼 6.2.1b
```python=
#0-dimension
arr0d = np.array(42)
#1-dimension
arr1d = np.array([1, 2, 3, 4, 5])
#2-dimension
arr2d = np.array([[1, 2, 3], [4, 5, 6]])
#3-dimension
arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]]])
#檢查維度(ndim)
print(arr0d.ndim)
print(arr1d.ndim)
print(arr2d.ndim)
print(arr3d.ndim)
#創建一個高維陣列(5-dimension)
arr = np.array([1, 2, 3, 4], ndmin = 5)
```
在Numpy這個章節當中,可以對於list和array進行大量比較,它們都可以建立多維陣列,其他的操作是否都夠通用?我們所知的是numpy.array運算速度遠快於list。
- [ ] 程式碼 6.2.1c
```python=
arr4 = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
print(arr4[0, 1, 2] + arr4[1, 0, 2])
#和list一樣,array也有負索引,因此可以用[-1]得到所求值
arr5 = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
print(arr5[1:7:2])#[起始:結束+1:遞增]
#和list一樣,array也可以切割取值
arr6 = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
print(arr6[1, 1:4])
print(arr6[1][1:4])#這兩行的效果一樣
print(arr6[0:2, 2])#下面的圖
```

:goat:**NumPy中的數據類型**
```i```- 整數
```b```- 布林值
```u```- 無符號整數
```f```- 浮點數
```c```- 複數
```m```- 時間
```M```- 日期
```O```- 物件
```S```- 字串
```U```- Unicode字符串
```V```- void
可以使用```print(array.dtype)```來獲取資料型態。
- [ ] 程式碼 6.2.1d
```python=
#直接將型態定義好
arr7 = np.array([1, 2, 3, 4], dtype='S4')#4-bytes,表示32位元容量
print(arr7)
print(arr7.dtype)
```
- [ ] 程式碼 6.2.1e
```python=
arr8 = np.array([1, 2, 3, 4, 5])
arr8_copy = arr8.copy()
arr8[0] = 42
#想修改資料,但怕失去原始資料,就弄一份副本吧
print(arr8)
print(arr8_copy)
```
#### 6.2.2 一點點的Matplotlib
大多數Matplotlib**實用**程序位於```pyplot```子模塊下,通常以```plt```別名導入。
Matplotlib也常常以```mpl```的姿態被導入。
##### 劃一條線
在圖表中從位置(0,0)到位置(6,250)畫一條線:
- [ ] 程式碼 6.2.2a
```python=
import matplotlib.pyplot as plt
import numpy as np#mpl常常搭配np
xpoints = np.array([0, 6])
ypoints = np.array([0, 250])
plt.plot(xpoints, ypoints)#plot()繪圖,show()展示
plt.show()
```

##### 劃幾個點
在圖中畫兩個點,一個在位置(1, 3),一個在位置(8, 10):
- [ ] 程式碼 6.2.2b
```python=
x2points = np.array([1, 8])
y2points = np.array([3, 10])
plt.plot(x2points, y2points, 'o')
plt.show()
```

##### 畫軌跡圖
畫軌跡圖,從位置(1, 3)到(2, 8),然後到(6, 1),最後到位置(8, 10):
- [ ] 程式碼 6.2.2c
```python=
xpoints = np.array([1, 2, 6, 8])
ypoints = np.array([3, 8, 1, 10])
plt.plot(xpoints, ypoints, color='#000000')
plt.plot(xpoints, ypoints, 'o', color='#000000')
plt.show()
```

在學習matplotlib時,可以知道一個魔法函數(據說前綴%的都是魔法函數)
```
%matplotlib inline
```
這邊有五段程式碼給你們回去玩~
##### 6.2.2d
- [ ] 程式碼 6.2.2d
```python=
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
%matplotlib inline
def x(R,a,phi_1,phi_2):
return((R+a*np.sin(phi_1))*np.cos(phi_2))
def y(R,a,phi_1,phi_2):
return((R+a*np.sin(phi_1))*np.sin(phi_2))
def z(a,phi_1):
return(a*np.cos(phi_1))
fig = plt.figure()
ax = fig.add_subplot(111,projection = '3d')
phi_1 = np.linspace(-2*np.pi, 2*np.pi, 50)
phi_2 = np.linspace(-2*np.pi, 2*np.pi, 50)
Phi_1, Phi_2 = np.meshgrid(phi_1, phi_2)
X = x(2,1,Phi_1,Phi_2)
Y = y(2,1,Phi_1,Phi_2)
Z = z(1,Phi_1)
ax.plot_surface(X, Y, Z, cmap=plt.cm.YlGnBu_r)
plt.show()
```

##### 6.2.2e
- [ ] 程式碼 6.2.2e
```python=
import matplotlib.pyplot as plt
import numpy as np
def f(x,y):
return (1-x/2+x**5+y**3)*np.exp(-x**2-y**2)+5
xx,yy = np.meshgrid(np.linspace(-3,3,50),np.linspace(-3,3,50))
zz = f(xx,yy)
plt.imshow(zz,origin='lower',extent=[xx.min(), xx.max(), yy.min(), yy.max()])
```

##### 6.2.2f
- [ ] 程式碼 6.2.2f
```python=
data = np.array([[ 0.45833279, 0.35737994, 0.54257486, 0.66908835],
[ 0.19544843, 0.48287855, 0.97316904, 0.25445816],
[ 0.44500619, 0.88060579, 0.74509425, 0.65703952],
[ 0.80474809, 0.48011234, 0.05086501, 0.47188907]])
fig, ax = plt.subplots()
heatmap = ax.pcolor(data, cmap=plt.cm.Greys)
# put the major ticks at the middle of each cell
ax.set_xticks(np.arange(data.shape[0])+0.5, minor=False)
ax.set_yticks(np.arange(data.shape[1])+0.5, minor=False)
# want a more natural, table-like display
ax.invert_yaxis()
ax.xaxis.tick_top()
ax.set_xticklabels(['a','b','c','d'], minor=False)
ax.set_yticklabels(['A','B','C','D'], minor=False)
cbar = plt.colorbar(heatmap)
```

##### 6.2.2g
- [ ] 程式碼 6.2.2g
```python=
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid.axislines import SubplotZero
width = 1 # 兩條柱之間的距離
num = 5 #柱的個數
ind = np.arange(num)
fig = plt.figure(figsize=(15, 4))
ax = SubplotZero(fig, 1, 3, 1)
ax1 = fig.add_subplot(ax)
means = [0.6481,0.6215,0.58,0.56,0.442]
stds = [0.0129,0.0119,0.01,0.009,0.003]
plt.bar(0.2+ind, means, 0.6*width,color=['k','r','c','y','r'], linewidth = 0.1, yerr=stds,error_kw=dict(elinewidth=1.5,ecolor='green'))
plt.axis([0,5,0,1])
plt.ylabel(u'wPrecision')
plt.grid()
plt.xticks([])
ax = SubplotZero(fig, 1, 3, 2)
ax2 = fig.add_subplot(ax)
means = [0.341,0.39,0.42,0.48,0.582]
stds = [0.0109,0.0149,0.02,0.011,0.009]
plt.bar(0.2+ind, means, 0.6*width, color=['k','r','c','y','r'], linewidth = 0.1, yerr=stds,error_kw=dict(elinewidth=1.5,ecolor='green'))
plt.axis([0,5,0,1])
plt.ylabel(u'wRecall')
plt.grid()
plt.xticks([])
ax = SubplotZero(fig, 1, 3, 3)
ax3 = fig.add_subplot(ax)
means = [0.68,0.6415,0.6,0.58,0.548]
stds = [0.02,0.0119,0.0099,0.009,0.007]
label = plt.bar(0.2+ind, means, 0.6*width, color=['k','r','c','y','r'],linewidth = 0.1, yerr=stds,error_kw=dict(elinewidth=1.5,ecolor='green'))
plt.axis([0,5,0,1])
plt.ylabel(u'wF1')
plt.grid()
plt.xticks([])
fig.legend((label[0], label[1],label[2], label[3],label[4]), ('SVD-Single', 'SVD-Multiple','JNE','SNE','R2P'), 'upper center' ,ncol=5)
```

##### 6.2.2h
- [ ] 程式碼 6.2.2h
```python=
fig = plt.figure()
rect=[0.1,0.1,0.8,0.8]
axprops = dict(xticks=[], yticks=[])
ax0=fig.add_axes(rect, label='ax0',**axprops)
imgP = plt.imread("怕爆.jpg")##去電腦找圖片
ax0.imshow(imgP)
ax1=fig.add_axes(rect, label='ax1',frameon=False)
x = linspace(0,10,100)
y = sin(x)
ax1.plot(x,y)
ax1.set_xlim([-2,12])
ax1.set_ylim([-5,12])
ax2=fig.add_axes(rect, label='ax2',frameon=False,**axprops)
shodow_x = np.array([4.2, 4.2, 5.7, 5.8])
shodow_y = np.array([5.6, 7.2, 7.2, 5.5])
ax2.set_xlim([-2,12])
ax2.set_ylim([-5,12])
ax2.fill(shodow_x, shodow_y, linewidth=0, alpha=0.4, color='r')
ax2.annotate('plot shadow area',xy=(5.7,7.2),xytext=(4.7,3.3),textcoords = 'offset points',arrowprops=dict(arrowstyle="->",connectionstyle="arc3"),fontsize=20)
plt.show()
```

:::success
:leaves:<font color=#227233><u>**Funny time**</u></font>
**1.** 由於實際上print的語法這麼一長串,
```print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False))```
我們可以嘗試更改它的```sep```、```end```...,像是
```python
print(1, 2, 3, 4, sep='✨', end='🤗')
```
**2.** 看看哪位勇者會想要打開這個潘朵拉盒子😏:
```
你只需要在純文字檔(.txt)上打上「%0|%0」這五個字符
接著將存文字檔另存為.bat檔 之後,執行這個bat檔
你的電腦的效能將會完全被消耗殆盡,直到當機、或者是你強制重開機為止~
```
想了解更多關於這種打開檔案就自動執行的內容,可以🔎"**批次檔(Batch file)**"
:::
## Homework 6
[ZeroJudge](https://zerojudge.tw)
* 本周題目:
<font color = gray>a134: 00948 - Fibonaccimal Base</font>
<font color = gray>a249: 00679 - Dropping Balls</font>
<font color = gray>a261: 10934 - Dropping water balloons</font>
<font color = gray>b421: 01077 - The Sky is the Limit 強化</font>
<font color = gray>c061: 00530 - Binomial Showdown</font>