###### tags: `Python 入門` Python 中的資料--物件 (object) 與內建函式 (builtin functions) = 在前一章中我們利用了 Python 的數學運算來熟悉交談模式的基本使用方式, 同時也學習有關 Python 語言的基本觀念, 這一章我們再深入探討 Python 的**物件觀念**。 ## 所有的資料都是物件 在 Python 中, `10` 這樣簡單的資料並不僅僅是個整數值而以, 所有 Python 中的資料都是以『**物件 (object)**』的形式存在, 你可以將物件視為是一個箱子, 裡面可以存放代表資料的各種『**值 (value)**』, 並且在箱子上提供有不同的按鈕, 可以進行不同的操作, 這些操作稱為『**方法 (methods)**』: ```graphviz digraph object { obj [label="{值 (value) ...|方法 (methods) ...}" shape=Mrecord]; } ``` 這些值與方法統稱為物件的『**特徵 (attributes)**』, 不同**類別 (class)** 的物件內可存放的值的數量、個別的值可表達的範圍與形式各有不同, 能夠操作的方法也不一樣。舉例來說, 像是 `10` 這種整數 (Integer) 物件, 只能存放一種值, 也就是整數 `10`, 可操作的方法則有 `__add__`、`__pow__`、.... 等等: ```graphviz digraph object { obj [label="{10|__add__\n__pow__\n...}" shape=Mrecord]; } ``` 我們可以使用以下的寫法對 10 操作 `__pow__` 方法, 就像是對於內含 10 的箱子按下 `__pow__` 按鈕一樣: ```Python >>> (10).__pow__(2) 100 ``` 對物件操作特定方法的方式就是**在物件與方法名稱之間加上 `.`**。這裡要特別注意的是加在 10 前後的括號是為了把 10 與之後的 `.` 隔開, 避免 Python 誤將 `.` 當成是小數點, 而把 `10.__pow__(2)` 誤會成帶有小數的資料, 這會因為其中含有底線及英文字母等而無法正確解譯成小數, 導致錯誤。方法名稱後要接著一對小括號, 並在括號中加入完成操作所需要的額外資料, 本例中使用的 `__pow__` 方法是計算次方, 需要提供次方數, 上述範例計算的就是 10 的 2 次方, 因此結果為 100。 :::warning :warning: 即使不需要提供額外資料, 操作方法時最後面的那一對小括號也不能省略, 一定要記得加上。 ::: ### 方法的叫用 (call) 與引數 (argument) 操作特定方法這樣的動作稱為『**叫用 (call)**』, 就是**叫出 (召喚)** 特定方法來**用**的意思。提供給方法的額外資料稱為『**引數 (argument)**』。**叫用方法**也是一種**運算式**, 因此在交談模式下, 會將叫用方法的結果顯示出來。 :::info :memo: 實際上 `10 ** 2` 就是以 `(10).__pow__(2)` 完成的, 像是這樣用來搭配運算器的方法稱為『**特別方法 (specail methods)**』, 只要物件具備有對應運算器的特別方法, 就可以使用運算式的寫法來操作, 比起叫用物件的方法更易於理解。 由於這樣的運作架構, 也代表同樣一個運算器, 對於不同類別的物件, 實際進行的可能是不同的運算, 端看個別物件內的特別方法而定, 後續遇到的時候我們會再特別提醒。 ::: 你也可以試試看不同類別的資料, 像是 Python 中對應於實數 (real numbers) 的資料類別叫做**浮點數 (floating-point number)**, 也就是帶有小數的數值, 這種資料具有 `__int__` 方法, 可以從浮點數捨去小數後產生一個整數物件, 例如: ```Python >>> 1.4.__int__() 1 ``` 就是叫用 `__int__` 方法來操作 1.4 這個浮點數, 捨去小數後得到整數 1。 :::warning :warning: 本例中 `1.4` 並不需要使用小括號括起來與 `.` 區隔, 因為 Python 可以從 `1.4.` 判斷出前面的 `1.4` 是浮點數, 接續的 `.` 不是浮點數值的一部份, 而是要叫用特定的方法。如果你覺得加上括號比較清楚, 也是可以的: ```python >>> (1.4).__int__() 1 ``` ::: :::info :memo: 浮點數名稱的由來, 是因為浮點數可以有多種寫法, 不同寫法時小數點的位置會跑來跑去, 例如以下都是 20.123: $2.0123\times{10^{1}}$、$2012.3\times{10^{-2}}$、$0.20123\times{10^{2}}$ 小數點的位置都不相同, 就像是把浮筒壓入水中, 但浮筒從不同地方浮出來一樣。 ::: ::: info :memo: 如果想知道 Python 提供有哪幾種不同類別的物件, 可以查看 [Python 線上文件](https://docs.python.org/3.4/library/stdtypes.html)。 ::: ## 查知物件可用的方法與所屬的類別--內建函式 (builtin-function) 為了幫助你完成某些工作, Python 除了像是運算器這些基本的功能外, 還透過『**內建函式 (builtin-function)**』的形式提供很多額外的功能讓你使用。例如, 如果你想知道某個物件具有哪些特徵, 可以使用 `dir` 這個內建函式: ```python! >>> dir(20.123) ['__abs__', '__add__', '__bool__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getformat__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__int__', '__le__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__pos__', '__pow__', '__radd__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rmod__', '__rmul__', '__round__', '__rpow__', '__rsub__', '__rtruediv__', '__set_format__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', 'as_integer_ratio', 'conjugate', 'fromhex', 'hex', 'imag', 'is_integer', 'real'] ``` 你可以看到內建函式的使用方式和前面叫用物件的方法很類似, 差別在於內建函式名稱之前不需要指定物件, 當然也沒有連接物件與方法名稱的 `.`。操作某個內建函式的動作也一樣稱為『**叫用**』。上例中我們就是將 20.123 當成**引數**叫用 `dir` 內建函式。 :::info :memo: 『**函式 (function)**』就是一段**事先寫好、具有名稱**的程式, 可以幫你完成一項特定的工作, 減少需要撰寫的程式量。像是 `dir` 這些在 Python 執行時就提供給你隨時可用的函式統稱為『**內建 (builtin)** 函式』, 表示是 Python 與生具有、不用額外動作就可以用的意思。 ::: `dir` 內建函式傳回的是『**串列 (list)**』類別的物件, 在交談模式中顯示時會以一對中括號表示。這裡我們先不管串列的細節, 你看到這一對中括號內以逗號區隔的就是 20.123 的特徵清單, 其中就有我們之前用過的 `__int__`。 同一種類別的物件都具有相同的特徵清單, 例如若把 3.5 當成引數叫用 `dir` 內建函式, 會得到: ```python! >>> dir(3.5) ['__abs__', '__add__', '__bool__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getformat__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__int__', '__le__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__pos__', '__pow__', '__radd__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rmod__', '__rmul__', '__round__', '__rpow__', '__rsub__', '__rtruediv__', '__set_format__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', 'as_integer_ratio', 'conjugate', 'fromhex', 'hex', 'imag', 'is_integer', 'real'] ``` 你會發現和剛剛看到的 `dir(20.123)` 結果是一樣的, 因為它們都是**浮點數物件**。 ## 查知物件的類別 如果你想知道某個物件是哪一種類別, 可以使用 `type` 這個內建函式, 像是這樣: ````Python >>> type(20.123) <class 'float'> ```` `type` 內建函式傳回的是 **type** 類別的物件, 專門負責記載特定類別的資訊, 每一種類別都對應到唯一一個專屬的 type 物件。這種物件在交談模式下會以 <class '類別名稱'> 的格式顯示, 在上例中就告訴我們這是**浮點數 (float)** 的 type 物件, 也就表示 20.123 是一個浮點數物件。 :::info :memo: 內建函式當然不只 `type` 和 `dir`, 後續我們使用到時, 還會再進一步介紹其他的內建函式。如果你想知道有哪些內建函式可用, 可以查閱 [Python 線上說明文件](https://docs.python.org/3.4/library/functions.html)。 ::: :::info :memo: 有個內建函式特別有趣, 叫做 `help`, 如果你不清楚某個內建函式或物件特徵的用途, 可以叫用 `help` 幫您查看看它的說明文件, 例如, 我們可以查 `dir` 的用途: ```python! >>> help(dir) Help on built-in function dir in module builtins: dir(...) dir([object]) -> list of strings If called without an argument, return the names in the current scope. Else, return an alphabetized list of names comprising (some of) the attributes .... ``` 最後一段就告訴你, 如果叫用時提供引數, 就會傳回該引數按照字母序排列的特徵清單。 ::: 瞭解 Python 中物件的概念是很重要的, 因為 Python 中的許多設計都和物件息息相關, 慢慢地就會越來越有感喔!