iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 4
1
Software Development

從零開始學Python系列 第 4

[Day 04] 從零開始學Python - 型態轉換及字串基礎:叫你印出來不是叫你開印表機阿!

註:本文同步刊載在Medium,若習慣Medium的話亦可去那邊看呦!

我們先來解答一下昨天的問題。
讀者的變數名稱可以自己定義,只要答案正確即可。
(但定義的時候,盡量是能夠表達出這個變數是用來做什麼的會比較好)
第一題的內容很簡單,就是把東西放進去計算,然後print出來。
範例解如下:

>>> pi=3.14
>>> r=7.77
>>> print(2*pi*r)  # 周長
48.7956
>>> print(pi*r**2) # 面積
189.57090599999998

請留意到,運算子之間有優先合併順序,這個可以Google一下會有詳盡的列表,
但簡單來說,就像小時候老師教先乘除後加減一樣,
pi*r**2這個式子來說,"**"這個運算子會先被優先納入計算,
所以r平方會先算完,再和左邊的pi相乘。

第二題呢?其實也只是加起來而已。

>>> pi=3.14
>>> r1=7.77
>>> r2=5.3
>>> r3=2.5
>>> print(2*pi*(r1+r2+r3))
97.7796
>>> print(pi*(r1**2+r2**2+r3**2))
297.398506

很簡單吧!

接下來第三天的部分,我們要來談一下型態轉換及一些字串的操作。
我們昨天已經提到有一些基本常見的型態:
bool, int, float, str,
也許讀者有想到一個問題:
兩個不一樣的型態是怎麼互相轉換的呢?
比方說我們先前在除法的時候,兩個int相除,
是會產生float的(如果不使用整數除法),
這個就是Python在這當中自動進行了型態轉換的部分。
有些時候,型態轉換則需要我們自己來操作,
比如int和float的互轉,只需要使用int()或float()即可。
我們來看一下int和float轉換的範例:

>>> float(1) # 從沒有小數點的int變成帶小數點的float
1.0
>>> int(1.0) # 很直觀XD
1
>>> int(1.6) # 咦? 不是2嗎?
1
>>> int(1.4)
1
>>> int(-1.1)
-1
>>> int(-2.1) # 所以是無條件捨棄
-2
>>> 1.5+1 # float和int相加
2.5
>>> 1+3.0  # 順序不影響
4.0

int轉換成float以後,就是多加.0在後面就對了!
float轉換成int的話,則是將小數點後面的東西全數捨棄
四則運算的話,int和float相遇最後結果會變成float,以求保留較多的資料。

那bool和int之間的關係呢?0會被當成偽,1會被當成真,
但是其他的數字(0以外的所有數字)也會被當成真呦!

>>> bool(0)
False
>>> bool(1)
True
>>> bool(3)
True
>>> bool(-2)
True
>>> int(True)
1
>>> int(False)
0

int還有其他變化,
可以將其轉換成用二進位/八進位/十六進位來表達。
所謂的二進位就是每個位數只有0或1兩種數字,
超過就進一位。

舉例來說,十進位的7等於二進位的111,
因為111等於1 * 2^2 + 1 * 2^1 + 1 * 2^0 = 4+2+1=7
(看不懂這段的,可以搜尋一下二進位,這邊不再贅述)
我們一般用X進位來表達數字時,稱這個X為「基數」。

在Python中如果數字用10以外的基數來表達時,
會額外做顯示上的處理:
二進位 -> 0b或0B (b代表binary)
八進位 -> 0o或0O (o代表octal)
十六進位 -> 0x或0X (x代表hexadecimal)
舉例來說:

>>> 0b10  # 2
2
>>> 0b111 # 4+2+1=7
7
>>> 0o11  # 8+1=9
9
>>> 0x1F  # 16+15=31 (A~F分別代表16進位的10~15)
31

上面這些有點枯燥我明白,但請記下來,有些東西將來會用上的XD

再來談談字串(str)吧!
在Python中,一個字串的資料,是用兩個單引號或兩個雙引號括起來的,
當int, float, bool等型態要轉為str時,
Python只有做一件事情:把它們加進引號中。(真是偷懶XD)

>>> str(9)
'9'
>>> str(97.1)
'97.1'
>>> str(True)
'True'
>>> str(0o11) # 以其他基數表達的int,仍會先轉回10進位再處理
'9'

那反方向呢?

>>> int('9')
9
>>> int('9.1') # python會跳出錯誤說:你騙我,它不是int!
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '9.1'
>>> float('9.1') # 這樣總符合了吧!
9.1
>>> bool('3') # 因為是0以外的東西,所以會是True
True

講到這裡,讀者可能會有疑問:
「前面講過print可以將東西印出來,
那我如果要印出字串,但裡面含單引號或雙引號呢?」
問的好!
由於有些特殊字元如單引號,雙引號等會有被拿去用的困擾,
所以當遇到會有特殊含義的字元,
或者要將特定字元轉換用途時,我們可以使用一個反斜線(\),
將原先的含義給轉換。
這邊請留意一下,在一般大多數的程式語言來說,
印出(print)通常代表把一些內容,輸出到螢幕上,
可能是程式的命令提示字元,或者別的東西,
但不是印表機!!!
請不要問為什麼我家沒有印表機筆者卻要你印出東西來的問題XD

比如我們想印出'We will rock you!' (連同單引號),
那麼,我們可以這樣子:

>>> print('\'We will rock you!\'') # 外層的單引號仍然是用來表達字串的開頭跟結尾,但內層的單引號被轉義回一般無特殊含義的單引號
'We will rock you!'

其他還有一些常用的轉義字元,但最常用的就是"\n"了,
可以用來做換行的效果!
舉例來說:

>>> print('天青色等煙雨 而我在等你\n炊煙裊裊升起 隔江千萬里')
天青色等煙雨 而我在等你
炊煙裊裊升起 隔江千萬里

你要多換幾行?那就多打幾個\n吧!
想同時印出多個字串的話,可以用逗號來連接,Python會幫忙在中間加空格。

>>> print('I\n','feel','good') # 即便換行,feel前面還是有一格空格
I
 feel good

再來談談Python中字串的一些常見的操作:
+結合、*複製、[]取字元、[start:end:step]切片、len()取長、split()分割、join()結合
以下是範例:

>>> 'a'+'b'+'c' # 相加就是串在一起就對了!
'abc'
>>> 'apple'*2   # 乘上的正整數相當於重複的次數
'appleapple'
>>> a = 'apple'
>>> a[3]        # 取第3位(從0起算)
'l'
>>> a[0:4:1]    # 切片slice: 從0開始,到4結束,每次跳1單位
'appl'
>>> a[0:4:2]    # 切片slice: 從0開始,到4結束,每次跳2單位
'ap'
>>> len(a)      # 取長度
5
>>> len(a[0:4:1]) # 剛剛切出的長度是4
4
>>> b = 'An apple a day, keeps the doctor away.'
>>> b.split() # 用括號內的字串來分割,預設是空白字元(換行/空格/位移tab)
['An', 'apple', 'a', 'day,', 'keeps', 'the', 'doctor', 'away.']
>>> b.split(',') # 用逗號來分割(留意用來分割的東西會不見)
['An apple a day', ' keeps the doctor away.']
>>> b.split('.') # 因為.的右邊沒東西,所以會多一個空字串
['An apple a day, keeps the doctor away', '']
>>> c = b.split()
>>> c
['An', 'apple', 'a', 'day,', 'keeps', 'the', 'doctor', 'away.']
>>> d = '\n'.join(c) # '字串'.join(要被接起來的串列)
>>> d
'An\napple\na\nday,\nkeeps\nthe\ndoctor\naway.'
>>> print(d) # 印出來的時候就知道\n是拿來換行了!
An
apple
a
day,
keeps
the
doctor
away.

程式碼內的註解應該足夠清楚,除了有幾點需要補充說明。
首先留意到a[3],在單獨中括號加上單一數字時,
代表從頭開始數到索引值(index)為3的地方,取出那個字元。
注意歐!這個算法中是從0開始數的!
也就是'apple'中的'a'是a[0],請讀者務必記得從0開始!
就算沒有在異世界生活也一樣XD

接著看到**[start:end:step]的切片部分,
它代表著我們可以用定好的規則來取出字串的片段。
其中:
start表示開始的位置;
end表示結束的位置,但是不含end這個位置;
step代表每次移動多少單位。

比方說剛剛的a[0:4:1],
就是從0開始,到4結束,每次移動1單位,但因為不包含4,
所以只會取到'appl'。
在step為正的情況下,start不寫的話,預設代表從0開始,
而step不寫的話,預設代表每次移動1單位

所以
a[0:4:1]也可以寫成a[:4:1]或者a[:4],讀者可以嘗試看看。
同理,end不寫的話代表預設到結束(包含尾端),
所以如
a[1:]就會是'pple'**。

此外,slice還有特異功能:當step是負數的時候,
前面不寫則代表預設從字串尾往字串頭走,
所以如a[::-1]會是'elppa',相當於將a反轉
a[4:1:-1]則是'elp'

而當start或end是負數的時候,
Python會將負數視作從尾往頭起算,如-1代表倒數第1個字元。
例如a[-2:0:-1]會是'lpp'

最後留意到split()作用過後,
會產生一個用中括號框起來,及逗號分隔的東西,
我們將其稱為list(串列,或稱列表),在接下來的文章中我們會介紹到它,
現在只需要知道,它就是一連串列出來的東西即可:
split會按照分割的字串將目標字串給切分開成列表;
join則會使用給定的字串將一個列表的所有東西按順序連接起來。

好的,最後我們來做個練習吧!

  1. 給定字串chs = 'abcdefghijklmnopqrstuvwxyz',請印出:
    1.1. 從z起算往回頭走,每次step為-2的字串
    1.2. 將索引值為16的字元,加上(索引值為14的字元重復2次),
    並用一個空格將前者和字串'有種果汁真好喝~'連接起來。
  2. 已知bin()的方法可以將一個int值用二進位表示並轉為字串,
    請嘗試給出36的二進位字串,但須去除'0b'的部分。
  3. 給定a, b, c = 'pen', 'apple', 'pine'
    (註:沒錯,你可以在一行同時生成多個變數,使用逗號隔開即可)
    請用a, b, c組合出'penpineappleapplepen'。

那就明天見囉!


上一篇
[Day 03] 從零開始學Python - 變數、型態、運算子:你的除法不是你的除法
下一篇
[Day 05] 從零開始學Python - 串列(list)、Tuple(元組)、字典(dict)、集合(set):我的字典裡沒有放棄,因為我還沒有寫進去(上)
系列文
從零開始學Python30

尚未有邦友留言

立即登入留言