🗺️ 程式互動式地圖
零基礎起步・第 3 課

數字、文字與型別轉換

明明輸入的是 3,程式卻說「不能把字串和整數相加」;10 除以 2 印出來是 5.0 而不是 5。這一課說明 Python 怎麼分辨「數字」和「長得像數字的文字」,以及兩者之間怎麼轉換。

型別:int、float、str、bool、None + - * / // % ** 與運算順序 input() 與 int()、float()、str()

💡 先搞懂問題

晴空咖啡的店長學了兩堂 Python,想寫一支小程式:問客人要買幾杯拿鐵,再算出總價。他寫了 cups = input("要買幾杯?"),接著 total = cups * 45。執行後輸入 3,畫面上沒有出現 135,而是一長串 333333…,數一數剛好 45 個 3。他改成先加運費 cups + 10,這次程式直接停下來,印出一行看不懂的 TypeError。另外他也發現,print(10 / 2) 印出來是 5.0,多了一個小數點。

這三件怪事的原因是同一個:Python 裡的每一筆資料都有「種類」,叫做型別(type)。數字 3 和用引號包起來的文字 "3" 長得很像,型別卻完全不同;同一個 * 或 +,碰到不同型別的資料,意思就不一樣,有時候根本不允許。而 input()(讓使用者從鍵盤打字的函式)交回來的,永遠是文字。

鍵盤輸入 3 input() 字串 str '3' * 45 + 10 int() '333…3' 把文字重複 45 次 TypeError 錯誤 文字加數字,意思說不清 整數 int 3 3 * 45 → 135 先轉型,再計算
同一個鍵盤輸入的 3,經過 input() 之後是字串 '3'(綠框)。上面兩條路照「文字」的規則處理,結果都不是店長要的;只有最下面先用 int() 轉成整數,乘法才是真正的乘法。

生活比喻:點餐單上的字,和真正的杯數

想像晴空咖啡的外場服務生幫客人點餐,在點餐單上寫下「拿鐵 3」。這張單子上的「3」只是筆寫的一個字。櫃台要算錢時,店員得先看懂這個字,在心裡把它當成「3 杯」,再乘上單價 45 元,算出 135 元。

如果有個新來的店員完全照字面操作呢?叫他「把單子上的 3 乘以 45」,他把那個字影印了 45 次,排成一長串 3;叫他「把單子上的 3 加上 10 元運費」,他就愣住了:是要在紙上再寫一個 10,還是把杯數加 10?這種說不清楚的要求,他乾脆不做。單子上如果寫的是「2.5」,要他照「整杯數」來讀,他也讀不出來,因為整杯數不會有小數點。

回到程式:點餐單上的字就是字串(string,簡寫 str);心裡讀出來的杯數是整數(integer,int),帶小數點的量是浮點數(floating-point number,float)。外場服務生就是 input():客人說什麼,它交回來的都是寫在單子上的字。「看懂字、讀成數量」對應 int() 與 float(),反過來把數量寫成字是 str()。那位照字面操作的新店員,就是完全不會替你猜意思的 Python:"3" * 45 是把文字重複 45 次,"3" + 10 直接報錯。
點餐單(比喻) Python 單子上手寫的「3」 字串 str:'3' 心裡讀出的「3 杯」 整數 int:3 帶小數的量「2.5 杯」 浮點數 float:2.5 服務生把聽到的寫成字 input() 一律回傳字串 看懂字,讀成數量 int()、float() 把數量寫回紙上 str() 把那個字影印 3 次 "3" * 3 → '333' 「字加 10 元」說不清楚 "3" + 10 → TypeError
左欄是點餐單的情境,右欄是 Python 裡對應的東西。前三列是三種資料,中間三列是「誰負責把字和數量互相轉換」,最後兩列是新店員照字面操作的結果。

比喻有三個地方和實際不同。第一,真實的店員看到「3」自然會當成 3 杯,Python 不會自動幫你轉換,一定要你自己寫 int(...)。第二,轉換不會把原本的字串「改掉」:cups = int(text) 是算出一個新的整數物件,再把名字 cups 貼上去,原本的 '3' 還在,text 也還貼在它上面。第三,紙上寫的 2.5 是精確的,電腦裡的浮點數卻是近似值,原理補完會用 0.1 + 0.2 說明。

型別屬於物件,不屬於名字

第 2 課說過,x = 5 是先算出右邊的值,再把名字 x 這張標籤貼到那個物件(object,記憶體裡真正的那筆資料)上。型別是物件本身的屬性:整數物件永遠是整數,名字只是標籤,撕下來改貼到字串上也可以。這一課會遇到五種最基本的型別:

int 整數,例如 45、-3、0;float 浮點數,就是有小數點的數,例如 45.0、2.5;str 字串,用引號包起來的文字,例如 "拿鐵"、"3";bool 布林值(boolean),只有 True(是)和 False(否)兩個值,第 7 課的條件判斷會大量用到;None 代表「沒有值」,例如還沒選優惠券。想知道某個物件是什麼型別,用 type(…),它會回答 <class 'int'> 這樣的字,意思是「整數型別」。

名字(變數) 物件(真正的資料,型別寫在這裡) 全域(主程式) priceavgtextmembercoupon 整數 int45 浮點數 float45.0 字串 str'3' 布林值 boolTrue NoneNone 能做算術45 和 45.0 值相等型別卻不同是文字,不是數是/否「沒有值」
這張圖和下面播放器的畫法一樣:左邊是名字,右邊是物件,箭頭表示名字貼在哪個物件上。注意型別標在右邊的物件上;名字本身沒有型別,同一個名字之後也可以改貼到別種型別的物件。

🎮 互動實驗室一:每個物件都有自己的型別

下面是一段真的用 Python 3.13 執行過的程式:晴空咖啡一杯拿鐵 45 元,客人買 3 杯。按「下一步」一次執行一行,右邊會畫出每個名字貼到哪個物件、物件是什麼型別。綠色箭頭 ➜ 指著「下一個要執行」的行;遇到 🤔 問題時先猜再按下一步,自動播放也會在那裡停下來等你。

畫面說明:特別注意第 4 行執行完的那一步:右欄多出一個 45.0,物件上方寫著「浮點數 float」,和最上面的 45(整數 int)是兩個不同的物件。135 / 3 明明剛好整除,用 / 算出來的還是浮點數。接著看第 7、8 行:// 和 % 算出的 2 和 35 又回到整數。最後兩行的 True、None 是橘色框,它們也是物件,名字同樣是用箭頭貼上去的。

🎮 互動實驗室二:input() 拿到的是字串

這次程式會用 input() 問「要買幾杯?」。播放器沒辦法真的讓你打字,所以準備了四種情況,用右上角的選單切換:使用者打 3 或 2.5,程式有轉換或忘了轉換。每一種都是 Python 3.13 真的執行出來的結果,包括錯誤訊息。

畫面說明:不管使用者打什麼,第 1 行執行完,text 都貼在綠框的字串上。① 和 ④ 只差在第 3 行用 int() 還是 float();② 的 text * 3 印出 333,程式沒有任何警告,下一行的 + 才出錯;③ 的錯誤類型不同,是 ValueError:型別沒問題,是字串的內容讀不成整數。出錯的那一步,下方輸出畫面會出現紅字的錯誤訊息(Traceback),最後一行就是錯誤類型和原因。
為什麼 input() 不直接給數字?因為它不知道你要什麼。使用者可能打名字、電話號碼(開頭的 0 不能丟)、「2.5」或亂打一串字。Python 一律先當成文字交給你,要不要轉成數字、轉成哪一種,由寫程式的人決定。

🎮 互動實驗室三:先猜再執行,12 張預測輸出卡

每張卡是一行程式,請先選出你認為畫面會印出什麼,再看 Python 3.13 實際的輸出和原因。如果會出錯,就選錯誤的名稱。答完按「下一張」,全部做完會顯示答對幾張;隨時可以按「重來」。

答對 0 / 0
連續答對 0
畫面說明:先看運算的兩邊是什麼型別:有引號的是字串,有小數點的是浮點數,其他數字是整數。再決定這個運算子在那個型別上代表什麼意思。

📘 原理補完

正式名稱與官方用語

Python 官方文件把語言本身提供的資料種類叫做內建型別(built-in types)。這一課的 int 與 float 屬於數值型別(numeric types),str 是文字序列型別(text sequence type),bool 只有 True、False 兩個值,None 則是 NoneType 這個型別唯一的值。+、* 這類符號叫運算子(operator),被運算的兩邊叫運算元(operand),整串 price * cups 叫做運算式(expression):運算式會被算成一個值,也就是一個物件。

大家常說的「轉型」(type conversion),在 Python 裡其實是「用型別的名字建立一個新物件」:int("42") 是請 int 這個型別根據字串 "42" 做出一個整數。所以轉型永遠產生新物件,不會改掉原本的東西。

算術運算子一覽

下表的結果都用 Python 3.13 實際算過。最常被問的是第四到第六列:/ 一律得到浮點數;// 是整除(floor division),只留下商往下取的整數;% 是取餘數(modulo)。整數和浮點數混在一起算時,結果是浮點數。

運算子名稱例子結果結果型別說明
+加7 + 29int兩邊都是整數,結果是整數
-減7 - 25int
*乘7 * 214int鍵盤沒有 ×,用星號
/除7 / 2、6 / 33.5、2.0float一定是 float,剛好整除也一樣
//整除7 // 23int只要商的整數部分(往下取)
%取餘數7 % 21int常用來判斷奇偶、找零
**次方7 ** 249int不是 ^
+(混合)加7 + 2.09.0float有一邊是 float,結果就是 float
+(字串)串接"ab" + "cd"'abcd'str兩邊都要是字串
*(字串)重複"ab" * 3'ababab'str字串乘整數
17 杯飲料,每個提袋裝 4 杯(示意) 剩 1 杯 4 個裝滿的提袋 17 / 4 → 4.25 17 // 4 → 4 17 % 4 → 1 平均每袋 4.25 杯結果是 float 裝滿了幾袋結果是 int 裝完還剩幾杯結果是 int
同樣是「17 和 4」,三個運算子回答三個不同的問題。// 和 % 是一對:17 = 4 × 4 + 1,// 給你前面的 4,% 給你最後的 1。

運算順序(優先順序)

一行算式裡有好幾個運算子時,Python 依照運算子優先順序(operator precedence)決定先算哪個,規則和數學課差不多:先算括號,再算 **,接著是 *、/、//、%,最後是 +、-;同一級的從左算到右,所以 10 - 4 - 3 是 3。不確定時就加括號,括號不會讓程式變慢,還能讓讀的人一眼看懂。

2 + 3 * 4 (2 + 3) * 4 2 + 12 5 * 4 14 20 先算 3 * 4括號先算再算加法再算乘法
黃框是第一步要算的部分。數字和運算子一模一樣,只差一對括號,答案就從 14 變成 20。

型別轉換:int()、float()、str()

轉換函式都是「讀一個物件、做出一個新物件」。最容易出事的是 int():它看得懂整數寫法的文字(前後的空白可以),看不懂小數點;用在浮點數上則是直接去掉小數部分,不是四捨五入。

寫法結果結果型別說明
int("42")42int文字讀成整數
int(" 7 ")7int前後空白會被忽略
int("3.5")ValueError—有小數點的文字,int() 讀不懂
int(3.9)3int浮點數轉整數:直接去掉小數,不會變 4
float("3.5")3.5float帶小數的文字要用 float()
float("3")3.0float整數寫法的文字也可以
float("abc")ValueError—不是數字的文字
str(135)'135'str數字寫成文字,才能和其他字串用 + 接起來
原本的物件 轉換函式 新的物件 '42' '3.5' '3.5' 3.9 135 7 int()int()float()int()str()float() 42 ValueError 3.5 3 '135' 7.0 去掉小數
綠框是字串,藍框是數字。左右兩欄是不同的物件:轉換一定是做出新的物件,原本的物件還留在原地。第二列是 int() 讀不懂小數點的文字;第四列的 3.9 變成 3,不是 4。

常見錯誤與錯誤訊息的長相

下面的訊息都是 Python 3.13 實際印出來的。最後一行最重要:冒號前面是錯誤類型,後面是原因。File "main.py", line 2 告訴你出錯的檔案和行號(在你的電腦上會是完整的檔案路徑),波浪線 ~ 和 ^ 標出出事的那一段。第 10 課會專門教怎麼讀這些訊息。

1. 字串 + 數字:TypeError(price 是字串 "45")
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    total = price + 10
            ~~~~~~^~~~
TypeError: can only concatenate str (not "int") to str
「只能把字串(str)接上字串,不能接 int」。修正:要算數就先轉 int(price) + 10;要接成文字就寫 price + str(10)。
2. 數字 + 字串:一樣是 TypeError,訊息不同
Traceback (most recent call last):
  File "main.py", line 1, in <module>
    print(10 + "5")
          ~~~^~~~~
TypeError: unsupported operand type(s) for +: 'int' and 'str'
左邊是整數時,訊息變成「+ 不支援 int 和 str 這兩種運算元」。兩種訊息都在說同一件事:型別對不上。
3. int() 讀不懂內容:ValueError
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    cups = int(text)
ValueError: invalid literal for int() with base 10: '3.5'
「'3.5' 不是 int() 看得懂的十進位整數寫法」。型別沒錯(確實是字串),是值的內容不對,所以叫 ValueError。使用者可能打小數時,改用 float(text)。
4. 除以 0:ZeroDivisionError
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    print(n / 0)
          ~~^~~
ZeroDivisionError: division by zero
/、//、% 的右邊都不能是 0。
5. 不會報錯的錯:字串乘整數 cups = input() 之後寫 cups * 45,Python 不會出錯,而是安安靜靜地給你 45 個重複的文字。沒有錯誤訊息的錯最難找,看到奇怪的輸出時,先用 type() 印出型別確認。

0.1 + 0.2 為什麼不是 0.3

電腦用二進位(只有 0 和 1)存數字。像 0.1 這樣的小數,換成二進位是無限循環的,只能存一個非常接近的值,所以浮點數存的是近似值。平常印出來看不到差異,但兩個近似值相加,誤差偶爾會露出來。

把 0.3 附近的數線放大很多很多倍(示意,不按比例) 0.3 你心裡的答案 0.30000000000000004 0.1 + 0.2 的結果 差距極小,但不是 0,所以 == 比較會得到 False
兩個點在一般尺度下完全重疊,只有放大到小數點後第 17 位才分得開。這不是 Python 的錯,幾乎所有程式語言的浮點數都一樣。

入門階段記住兩件事就夠了:要顯示給人看時,用 round(x, 2) 四捨五入到需要的位數(第 4 課的 f-string 也能控制小數位數);不要用 == 直接比較兩個浮點數是否相等。真的要處理金額,實務上會用整數存「分」或使用 decimal 模組,等學完基礎再看就好。

完整範例一:結帳程式(轉型、混合運算、印出結果)

# 晴空咖啡結帳:input() 拿到的一律是字串,這裡先用寫死的字串模擬
cups_text = "3"              # 使用者打的「3」
price_text = "45.5"          # 使用者打的「45.5」

cups = int(cups_text)        # "3" → 3(整數 int)
price = float(price_text)    # "45.5" → 45.5(浮點數 float)
total = cups * price         # int 和 float 一起算,結果是 float
print(total)                 # 136.5
print(type(cups), type(price), type(total))

print("總共 " + str(total) + " 元")   # 數字先用 str() 轉成文字,才能用 + 接起來
print("總共", total, "元")           # 也可以交給 print:用逗號分開,它會自己轉成文字
136.5
<class 'int'> <class 'float'> <class 'float'>
總共 136.5 元
總共 136.5 元

最後兩行印出一樣的結果。用 + 串接時要自己處理型別和空格;用逗號交給 print 時,它會把每個值轉成文字、中間自動加一個空格。

完整範例二:整除、餘數與運算順序

# 135 分鐘是幾小時幾分?// 拿整除的部分,% 拿餘數
minutes = 135
hours = minutes // 60        # 135 裡面有幾個完整的 60 → 2
rest = minutes % 60          # 拿走 2 個 60 之後還剩多少 → 15
print(hours, "小時", rest, "分鐘")   # 2 小時 15 分鐘
print(minutes / 60)          # 2.25:/ 一律得到 float,會保留小數

# 運算順序:** 先算,再來 * / // %,最後 + -;有括號先算括號
print(2 + 3 * 4)             # 14:先算 3 * 4
print((2 + 3) * 4)           # 20:括號裡先算
print(2 * 3 ** 2)            # 18:先算 3 ** 2 = 9
2 小時 15 分鐘
2.25
14
20
18

完整範例三:浮點數誤差

# 浮點數是用二進位「近似」小數,偶爾會差一點點
a = 0.1 + 0.2
print(a)                     # 0.30000000000000004
print(a == 0.3)              # False:兩個近似值剛好不一樣
print(round(a, 2))           # 0.3:要顯示給人看時,四捨五入到需要的位數
0.30000000000000004
False
0.3

以後在哪裡會再遇到

讀 AI 或資料分析的範例程式時,型別問題會換個樣子出現。用 pandas 讀進 CSV 檔,如果某一欄的數字裡混了「無」或「1,200」這種寫法,整欄都會被當成文字,直接算平均就會出錯,得先轉成數字;NumPy 陣列也有自己的型別(dtype),整數陣列和浮點數陣列算出來的結果不一樣。這些都是同一個觀念:先看清楚資料是什麼型別,再決定能做什麼運算。

✅ 自我檢測

6 題都是小段程式,輸出都用 Python 3.13 實際跑過。選完會立即顯示對錯與解析,全部作答後會出現總分。目前得分:0 / 6