Learning Objectives
- 使用 Python 數值資料型態:int、float、complex
- 了解隱含與明確的數值型態轉換:int()、float()、complex()
- 解釋可變(mutable)與不可變(immutable)資料型態
- 凡事皆物件(objects):每個物件都有 identity、type、value,變數是物件的參考
凡事皆物件
在 Python 的世界裡,一切都是物件(Everything is an object):數字、字串、串列,甚至函數都是。 每一個物件都有三個屬性:
| 屬性 | 意義 | 怎麼查看 | 會不會改變 |
|---|---|---|---|
| identity | 物件在記憶體中的身分(可以想成位址) | id();比較兩個物件用 is |
建立之後就不會改變 |
| type | 物件的型態,決定能存什麼、能做哪些運算 | type() |
建立之後就不會改變 |
| value | 物件的值 | 直接印出 | 有些物件可以改(可變),有些不行(不可變) |
上一課說過,變數是指向物件的名稱,所以更精確地說:所有變數都是物件的參考。 這一課先認識最基本的物件:數值。
Python 內建的資料型態:
| 分類 | 型態 |
|---|---|
| 數值(Numeric) | int、float、complex |
| 有序(Sequence) | list、tuple、range |
| 文字(Text Sequence) | str |
| 集合(Set) | set、frozenset |
| 對應(Mapping) | dict |
| 二進位(Binary Sequence) | bytes、bytearray、memoryview |
三種數值型態
| 型態 | 說明 | 範例 |
|---|---|---|
int(整數) |
正負整數,沒有小數點;Python 3 的整數沒有最大值限制 | 10、-336、0b110、-0o40、0x6A |
float(浮點數) |
實數,有小數點;可以用科學記號 | 0.0、-21.9、45.3e+5、-70.、58.2E-8 |
complex(複數) |
a + bj,a 是實部、b 是虛部,j 代表 √-1 |
3.14j、-.9815+0J、3e+36J |
0b/0B開頭是二進位,0o/0O是八進位,0x/0X是十六進位e/E代表科學記號:2.5e2是 2.5 × 10²=250.0- 這些符號以及複數的
j都不分大小寫 - 布林值
True、False其實是整數的子型態,分別等於 1 和 0 - 複數在資料科學領域比較少用,知道寫法即可
寫出各種數值
右邊的變數面板會顯示每個變數的值。注意二進位、八進位、十六進位寫法存進去之後,都是一般的整數;type() 告訴你一個物件是什麼型態。
整數沒有上限,浮點數有
很多語言的整數有最大值,超過就會出錯;Python 3 的整數可以任意大。浮點數則有固定的範圍,超過時會發生 OverflowError。範例用 try/except 接住這個錯誤(Module 17 會詳細介紹例外處理)。
0.1 + 0.2 等於 0.3 嗎?
電腦用二進位儲存浮點數,像 0.1 這樣的數在二進位是無限循環小數,只能存近似值。所以 0.1 + 0.2 不會剛好等於 0.3。這不是 Python 的錯誤,幾乎所有程式語言都一樣。
數值型態轉換
隱含轉換:不同的數值型態一起運算時,Python 會自動把結果轉成比較「寬」的型態:
bool→int→float→complex
例如 3 + 2.0 得到浮點數 5.0。
明確轉換:用內建函數自己指定要轉成什麼型態:
| 函數 | 結果 | 範例 |
|---|---|---|
int(x) |
轉成整數,小數直接捨去(往 0 的方向,不是四捨五入) | int(3.9) → 3、int(-3.9) → -3 |
float(x) |
轉成浮點數 | float(20) → 20.0 |
complex(x) |
轉成複數,虛部為 0 | complex(5) → (5+0j) |
complex(x, y) |
實部為 x、虛部為 y | complex(5, -2) → (5-2j) |
int()、float() 也可以把字串轉成數字,例如 int("42")。input() 讀到的永遠是字串,要計算前一定要先轉換。
隱含轉換與明確轉換
前三行看 Python 自動轉換型態,後面看 int()、float()、complex() 的效果。第 14 行特別有意思:同樣是 + 1,對字串和對整數的結果完全不同。
可變與不可變
物件的 identity 和 type 建立後就不會變,但 value 能不能改,要看型態:
| 型態 | |
|---|---|
| 不可變(immutable) | 數值 int、float、complex;字串 str;元組 tuple;凍結集合 frozenset |
| 可變(mutable) | 串列 list、字典 dict、集合 set |
數值是不可變的。所以
var1 = 10
var1 = 20
並不是把物件 10「改成」20,而是建立(或取用)另一個物件 20,再讓 var1 改指向它;
原本的 10 沒有被改動。要判斷兩個名稱是不是指向同一個物件,用 is。
這個觀念對後面的串列、字典與函數參數非常重要:改變可變物件時,所有指向它的名稱都看得到變化; 不可變物件則永遠不會被「就地修改」。
數值不可變:重新指定就是換一個物件
觀察變數面板裡箭頭指向哪個物件,以及 is 的結果什麼時候從 True 變成 False。最後四行說明:型態是物件的屬性,同一個名稱指向不同物件,type() 的結果就跟著變。
想一想:數值與轉換
下面的程式會印出什麼?
print(type(6 / 3))
下面的程式會印出什麼?
print(int(-2.7), int(2.7))
下面的程式會印出什麼?
print(0x10 + 0b10)
想一想:浮點數與不可變
下面的程式會印出什麼?
print(0.1 + 0.2 == 0.3)
下面的程式會印出什麼?
a = 5
b = a
a += 1
print(a, b, a is b)
下面哪一種型態是可變的(mutable)?
實作:把字串轉成數字再計算
身高和體重存成了字串(就像 input() 讀到的資料)。把它們轉成數字,計算 BMI=體重(公斤)÷ 身高(公尺)²,用 round() 四捨五入到小數第 1 位,印出 BMI = 22.5。
重點精華回顧
- 凡事皆物件:每個物件有 identity(用
is比較)、type(用type()查看)與 value;所有變數都是物件的參考。 - 數值型態:
int(沒有上限,可用0b、0o、0x寫法)、float(有小數點、可用科學記號、有範圍上限)、complex(a + bj);bool是int的子型態。 - 浮點數是近似值:
0.1 + 0.2 != 0.3,比較時用math.isclose();round()遇到一半時取偶數。 - 隱含轉換往較寬的型態走(bool → int → float → complex);明確轉換用
int()、float()、complex(),int()是往 0 捨去。 - 數值是不可變的:重新指定或
+=都是讓名稱改指向另一個物件;串列、字典、集合才是可變的。