{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "<p style=\"text-align:center\">\n", " <a href=\"https://nbviewer.jupyter.org/github/twMr7/Python-Machine-Learning/blob/master/02-Syntax_Overview_1.ipynb\">\n", " Open In Jupyter nbviewer\n", " <img style=\"float: center;\" src=\"https://nbviewer.jupyter.org/static/img/nav_logo.svg\" width=\"120\" />\n", " </a>\n", "</p>" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[](https://colab.research.google.com/github/twMr7/Python-Machine-Learning/blob/master/02-Syntax_Overview_1.ipynb)\n", "\n", "# 2. 語法概要(上) Syntax Overview 1\n", "\n", "程式語言的核心任務,主要就是數值的運算或對資料的操作。本章首先針對常用的資料、容器類型以及基本的操作方式作概觀性的介紹:\n", "\n", "+ [**2.1 資料型別(Data types)**](#object-types)\n", "+ [**2.2 操作運算子(Operators)**](#operators)\n", "+ [**2.3 變數與物件(Variable and Object)**](#variable-and-object)\n", "+ [**2.4 序列容器的操作(Sequence Operations)**](#sequence-operations)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<a id=\"object-types\"></a>\n", "\n", "## 2.1 資料型別 Data Types\n", "\n", "對 Python 來說,程式碼裡操作的所有東西都是物件(Object),所以比較正確的來說,我們會介紹的是 Python 裡的物件型別(Object types)。Python常用的內建物件包含了**數值**(Number)、**序列**(Sequence)、**集合**(Set)、**對應集**(Mapping)資料型別,以及**檔案**和**None**等物件。主要的資料型別裡,有的物件型別的資料內容可以就地變更(Mutable),有的不能就地變更(Immutable),常用型別的如以下表格所列。\n", "\n", "| 物件類型 | Mutability | 內建物件型別 |\n", "|-----------|--------------|-----------------------------------------|\n", "| 數值 | *immutable* | **`int`, `bool`, `float`, `complex`** |\n", "| 序列 | *mutable* | **`list`, `bytearray`** |\n", "| 序列 | *immutable* | **`str`, `tuple`, `bytes`** |\n", "| 對應集 | *mutable* | **`dict`** |\n", "| 集合 | *mutable* | **`set`** |\n", "| 檔案/串流 | n/a | **`file`** |\n", "| NoneType | n/a | **`None`** |\n", "\n", "- 內建函式 `type()` 可以用來檢驗物件的型態。\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<a id=\"numbers\"></a>\n", "\n", "### § 數值 Numbers\n", "| 型別 | 範例 |\n", "|-------------|-------------------------------------------------------|\n", "| **int** | `1234`, `−24` ,`0`, `0x9ff`(十六進位), `0b1111`(二進位)|\n", "| **bool** | `True`(1), `False` (0) |\n", "| **float** | `1.23`, `3.14e-10`, `4E210`, `4.0e+210`, `1.`, `.1` |\n", "| **complex** | `3+4j`, `3.0+4.0j`, `3J` |\n", "\n", "- 內建函式 `int()`、`float()`、`complex()` 可以用來將字串轉換成數值類型。\n", "- 內建函式 `ord()` 可以用來將字元轉換成對應的字碼值,是 `chr()` 的逆向操作。\n", "- 內建函式 `print()` 可以用來將數值內容輸出至畫面。\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(int, float, float)" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 小小的小數點很容易被忽略,有沒有一個小點是不一樣的\n", "type(17), type(17.), type(.17)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(True, True)" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 布林值是整數 int 的子類別,但不是用來作數值運算的,主要用於流程控制時的條件判斷\n", "type(False) is bool, type(True) == bool" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "number1 = 65 , number2 = 0.001\n" ] } ], "source": [ "# 從字串轉換成數值\n", "print('number1 =', int('0x41', base=16), ', number2 =', float(' 1e-003 \\n'))" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(65, 'A')" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 字元 'A' 的 ASCII 碼\n", "ord('A'), chr(0x41)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<a id=\"string\"></a>\n", "\n", "### § `str` 字串\n", "\n", "[`str`](https://docs.python.org/3/library/stdtypes.html#text-sequence-type-str)字串是以字元為元素的序列資料結構,字串的語法使用單引號或雙引號包起來,一樣的引號要成對使用。\n", "\n", "元素內容是按照儲存順序的 index 存取,語法為 **`[ index ]`**。 如果按照由前往後的順序,**第一個元素 index 是0**,依次往後遞增; 如果反過來由後往前存取,**最後一個元素 index 可以用-1**,依次向前遞減。\n", "\n", "| 字串範例 | 說明 |\n", "|------------------------------|-----------------------------------------------|\n", "| `''` | 空字串 |\n", "| `\"Python's\"`, `'Python\"s'` | 字串用單引號或雙引號包起來 |\n", "| `'Python\\'s\\n'` | 特殊字元前面要加反斜線 `\\` |\n", "| `r'c:\\Users\\name'` | 引號前置碼`r`保留字串呈現的原貌(raw string) |\n", "| `\"This\" \"is\" \"concatenated\"` | 相鄰的字串會自動被串接起來 |\n", "\n", "- 內建函式 `str()` 回傳物件的字串版本。\n", "- 內建函式 `hex()`、`bin()` 分別可以用來將數值轉換成十六進位及二進位的數字字串。\n", "- 內建函式 `chr()` 可以用來將字碼轉換成對應的字元,是 `ord()` 的逆向操作。\n", "- 內建函式 `len()` 可以用來回傳字串的長度。\n", "- 內建函式 `print()` 可以用來將字串內容輸出至畫面。\n" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "拍神\t好\n", "好玩\n" ] } ], "source": [ "# 包含特殊字元的字串\n", "print('拍神\\t' '好\\n' '好玩')" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "拍神好好玩\n" ] }, { "data": { "text/plain": [ "(None, 5)" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 相鄰的字串視為串接起來的一個字串\n", "print('拍神' '好' '好玩'), len('拍神' '好' '好玩')" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(False, True, True)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 當用於邏輯條件判斷時,空字串視為 False,其他則視為 True\n", "bool(''), bool('any string'), bool('False')" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(65, '0x41', '0b1000001')" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 輸出不同進位制的數字字串\n", "ord('A'), hex(ord('A')), bin(ord('A'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<a id=\"list\"></a>\n", "\n", "### § `list` 序列容器\n", "\n", "[`list`](https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range) 是存放序列性資料的結構。語法使用逗號 `,` 分隔資料元素,用中括號(square brackets)`[` `]` 成對包住所有元素。`list`可以是巢狀多維度的,同一個`list`中也可以存放異質類型資料,不過一般使用情境還是以同類型的資料較適合。\n", "\n", "元素內容是按照儲存順序的 index 存取,語法為 **`[ index ]`**。 如果按照由前往後的順序,**第一個元素 index 是0**,依次往後遞增; 如果反過來由後往前存取,**最後一個元素 index 可以用-1**,依次向前遞減。 \n", "\n", "| List 範例 | 說明 |\n", "|------------------------------------|-----------------------------------------------|\n", "| `[]` | 空的 list |\n", "| `[5, 6, 7, 8]` | 四個數字元素的 list |\n", "| `['code', [42, 3.1415], 1.23, {}]` | 巢狀、異質的 list |\n", "\n", "- 內建函式 `list()` 可以用來從現有物件的資料實體中生成一個新的list。\n", "- 內建函式 `len()` 可以用來回傳容器裡的元素個數。\n", "- 內建函式 `min()` 可以用來回傳容器中最小的元素。\n", "- 內建函式 `max()` 可以用來回傳容器中最大的元素。\n" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 利用內建函式 range(stop) 產生整數數列的 List\n", "# range 預設從 0 開始直到指定的整數“的前一個整數”\n", "list(range(10))" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9]" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 也可以分別指定開始、結束、及區間間隔 range(start, stop, step)\n", "L = list(range(9, -10, -1))\n", "L" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(9, -9)" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 用 index 存取 List 元素\n", "L[0], L[len(L) - 1]" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(-9, 9)" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 搭配使用內建函式\n", "min(L), max(L)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(False, True)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 空的 List 在邏輯上是 False\n", "bool([]), list(range(0)) == []" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<a id=\"tuple\"></a>\n", "\n", "### § `tuple` 序列容器\n", "\n", "[`tuple`](https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range) 也是存放序列性資料的結構。語法使用逗號 `,` 分隔資料元素,用小括號(parentheses)`(` `)` 成對包住所有元素,但括號可以省略。 `tuple`可以是巢狀多維度的,同一個`tuple`中也可以存放異質類型資料,通常使用在函式參數的傳遞與回傳。\n", "\n", "元素內容是按照儲存順序的 index 存取,語法為 **`[ index ]`**。 如果按照由前往後的順序,**第一個元素 index 是0**,依次往後遞增; 如果反過來由後往前存取,**最後一個元素 index 可以用-1**,依次向前遞減。\n", "\n", "| tuple 範例 | 說明 |\n", "|------------------------------------|-----------------------------------------------|\n", "| `()` | 空的 tuple |\n", "| `('code',)` | 單一元素的 tuple |\n", "| `(5, 6, 7, 8)` | 四個數字元素的 tuple |\n", "| `('code', (42, 3.1415), 1.23, {})` | 巢狀、異質的 tuple |\n", "| `'code', 42, 3.1415, 1.23` | 括號可以省略 |\n", "\n", "- 內建函式 `tuple()` 可以用來從現有物件的資料實體中生成一個新的tuple。\n", "- 內建函式 `len()` 可以用來回傳容器裡的元素個數。\n", "- 內建函式 `min()` 可以用來回傳容器中最小的元素。\n", "- 內建函式 `max()` 可以用來回傳容器中最大的元素。" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 單一元素 tuple 的表示比較特殊,逗號不能省略\n", "tuple([99]) == (99,)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(1, 3, 5, 7, 9)" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 內建函式 range() 一樣可以用來幫忙產生整數數列的 tuple\n", "t = tuple(range(1, 10, 2))\n", "t" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(1, 9, 5, 1, 9)" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 用 index 存取 tuple 元素,以及內建函式的使用\n", "t[0], t[4], len(t), min(t), max(t)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<a id=\"dict\"></a>\n", "\n", "### § `dict` 字典容器\n", "\n", "[`dict`](https://docs.python.org/3/library/stdtypes.html#mapping-types-dict) 是非序列式的資料結構,元素內容的儲存是成對的 key 和對應的 value。語法使用冒號組成 key 和 value 對應組 `key:value`,以逗號 `,` 分隔對應組元素,用大括號(curly braces)`{` `}` 成對包住所有元素。 同一個 `dict` 中的 `value` 可以存放異質類型資料。`dict` 也可以是巢狀的,也就是 `value` 中含有另外一個 `dict` 類型的資料。\n", "\n", "元素內容必須用 `key` 來存取,語法為 **`[ key ]`**。\n", "\n", "| dict 範例 | 說明 |\n", "|------------------------------------|-----------------------------------------------|\n", "| `{}` | 空的 dict |\n", "| `{'alpha': 2, 'beta': 3}` | 兩個元素的 dict |\n", "| `{ 'parameter': { 42: 1.5, 'angle': 30 }, 'date': ['2018-06-08'] }` | 巢狀、異質的 dict |\n", "| `dict([['a', 1], ['b', 2], ['c', 3]])` | 由list中建構一個新的dict物件 |\n", "\n", "- 內建函式 `dict()` 可以用來從現有物件的資料實體中生成一個新的字典容器。\n", "- 內建函式 `len()` 可以用來回傳容器裡key-value對的個數。" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "('鮑伯', True)" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Dict 非常適合用在非同質性資料組成的記錄集\n", "d1 = {'name':'鮑伯', 'age':45, 'job':('經理', '研發')}\n", "d1['name'], d1['age'] < 50" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "one two three\n" ] } ], "source": [ "# 由 List 中對應元素產生\n", "d2 = dict([[1, 'one'], [2, 'two'], [3, 'three']])\n", "print(d2[1], d2[2], d2[3])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<a id=\"sets\"></a>\n", "\n", "### § `set` 集合容器\n", "\n", "[`set`](https://docs.python.org/3/library/stdtypes.html#set-types-set-frozenset) 是非序列式、元素內容不重複的資料結構,提供了數學集合運算方法的支援,如聯集(union)、交集(intersection)、差集(difference)、對稱差(symmetric difference)。 可以使用大括號`{` `}`或`set()`函式建立集合物件,集合成員以逗號`,`分隔。 雖然不是序列式的容器,但是 `set` 物件也支援逐項元素存取的 *iteration* 操作。\n", "\n", "| set 範例 | 說明 |\n", "|----------------------------------------|----------------------------------------|\n", "| `set()` | 空的集合,注意不能用 `{}` |\n", "| `{'apple', 'orange'}` | 兩個元素的集合 |\n", "| `{'orange', 'banana', 5, ('pear',20)}` | 異質元素的集合 |\n", "| `set(['a', 'b', 'c'])` | 由 list 中建構一個新的集合物件 |\n", "\n", "- 內建函式 `set()` 可以用來從現有物件的資料實體中生成一個新的集合。\n", "- 內建函式 `len()` 可以用來回傳容器裡元素成員的個數。" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "集合1: {'a', 'r', 'd', 'b', 'c'}\n", "集合2: {'a', 'l', 'm', 'z', 'c'}\n" ] } ], "source": [ "s1 = set('abracadabra')\n", "s2 = set('alacazam')\n", "\n", "print('集合1: ', s1)\n", "print('集合2: ', s2)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'a', 'b', 'c', 'd', 'l', 'm', 'r', 'z'}" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 聯集:所有集合1與集合2有出現的元素\n", "s1 | s2" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'a', 'c'}" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 交集:同時有出現在兩個集合的元素\n", "s1 & s2" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'b', 'd', 'r'}" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 差集:只在集合1,不在集合2的元素\n", "s1 - s2" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'b', 'd', 'l', 'm', 'r', 'z'}" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 對稱差:沒有同時出現在兩個集合的元素\n", "s1 ^ s2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<a id=\"operators\"></a>\n", "## 2.2 操作運算子 Operators\n", "\n", "<a id=\"numeric-and-arithmetic\"></a>\n", "### § 數值與算術運算 Numeric and Arithmetic Operations\n", "| 算數的操作 | 說明 |\n", "|--------------------|--------------|\n", "| **X + Y, X - Y** | 加法,減法 |\n", "| **X \\* Y, X / Y** | 乘法,除法 |\n", "| **X // Y, X % Y** | 取商,取餘數 |\n", "| **X\\*\\*Y** | 次方 |\n", "| **X | Y, X & Y** | 位元 OR,AND |\n", "| **X ^ Y, ~X** | 位元 XOR,NOT |\n", "| **X << Y, X >> Y** | 位元左位移,右位移 |\n" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "302" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 數值運算範例 - 計算一個很大的數字有幾位數\n", "len(str(2 ** 1000))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "這些運算子不是只有數值可以用。 這是物件導向的一個重要的特質叫***多型*** : 相同概念的方法,行為會因為作用在不同類型的物件而有所改變。" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'拍神好棒棒拍神好棒棒拍神好棒棒'" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 字串支援 '+' 和 '*' 的運算\n", "p = '拍神' + '好棒棒'\n", "p * 3" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['拍', '神', '好', '棒', '棒', 1, 2, 3, '拍', '神', '好', '棒', '棒', 1, 2, 3]" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# List 與同樣是序列容器的字串一樣,支援 '+' 和 '*' 的運算\n", "L = list(p) + [1, 2, 3]\n", "L * 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### § 布林運算 Boolean Operations\n", "\n", "| 布林的運算 | 程式解譯邏輯 | 說明 |\n", "|-------------|-------------------------------------|--------------------------------------|\n", "| **X or Y** | 假如X為False則Y,否則X。 | 其中一個為True就是True,否則是False |\n", "| **X and Y** | 假如X為False則X,否則Y。 | 兩個都為True才是True,否則是False |\n", "| **not X** | 假如X為False則True,否則False。 | 反轉 |\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### § 比較運算 Comparisons Operations\n", "\n", "| 比較的運算 | 說明 |\n", "|----------------|--------------|\n", "| **X < Y** | 小於 |\n", "| **X <= Y** | 小於或等於 |\n", "| **X > Y** | 大於 |\n", "| **X >= Y** | 大於或等於 |\n", "| **X == Y** | 等於 |\n", "| **X != Y** | 不等於 |\n", "| **X is Y** | 是否相同物件 |\n", "| **X is not Y** | 是否不同物件 |\n", "\n", "- 對於容器物件的直接比較, ***“大於”*** 和 ***“小於”*** 的概念可能時常沒什麼太大意義, ***“等於”*** 或 ***“不等於”*** 則時常用到。\n", "- 物件在電腦裡都有一個對應的記憶體存放位址,可以用 `id()` 取得。 當 `is` 比較兩個物件是否相同時,實際比較的就是兩個物件是否有相同 `id()`。\n" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(int, float, True)" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 不同的數值型態可以互相比較(實際上是,int 2會先被自動轉型提升為 float,再進行比較)\n", "type(2), type(2.0), 2 == 2.0" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(True, False, False, True)" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 兩個字串用比較運算子時,方法是從第一個字元開始,比較出現第一個不同字元的 ASCII 碼(ord())的大小\n", "s1 = 'This is a book'; s2 = 'That is a book'\n", "'i' > 'a', s1 < s2, s1 == s2, s1 > s2" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(True, False, False)" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 兩個 List 或兩個 Tuple 用比較運算子時,方法是從第一個元素開始,比較出現第一個不同元素的大小\n", "L1 = [1, 2, 3, 4, 5]; L2 = [1, 2, 4]\n", "L1 < L2, L1 == L2, L1 > L2" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 不同型別不能作比較,除了(型別1 == 型別2)永遠回傳 False 以外,其他的比較都會出現 TypeError 的錯誤\n", "17 == '17'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<a id=\"variable-and-object\"></a>\n", "\n", "## 2.3 變數與物件 Variable and Object\n", "\n", "### § 指派述句 Assignment Statements\n", "Python是**動態型別(dynamic type)**的程式語言。為資料或物件指定變數名字時,程式碼中不需要明確宣告變數的型別。例如:當指定 `a = 3` 時,Python 會根據你的要求做這些步驟:\n", "1. 判斷 3 屬於 int 型別。\n", "2. 建立一個 3 的 int 物件。\n", "3. 建立一個名字叫做 a 的變數(如果原本 a 不存在)。\n", "4. 把變數 a 參考到物件 3 的關係連結起來。\n", "\n", "是**物件擁有型別**,不是變數。變數只是個指向參考物件的名字而已。" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "<class 'int'>\n", "<class 'str'>\n", "<class 'list'>\n" ] } ], "source": [ "a = 3\n", "print(type(a))\n", "\n", "# 改變 a 參考的物件\n", "a = 'a string'\n", "print(type(a))\n", "\n", "# 再一次改變 a 參考的物件\n", "a = [5, 6, 7]\n", "print(type(a))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### § 強型別 Strongly Typed\n", "\n", "Python是強型別(strongly typed)的程式語言。在操作運算兩個不同型別的物件時,不相容的型別不會私下自動轉換(implicit type conversions)。程式設計員必須明確知道要的操作運算是甚麼,自己明確指定型別轉換。\n", "\n", "如果知道字串內容是數字的格式,可以用 int(), bool(), float(), complex() 來轉型。 而幾乎所有的物件都可以使用 str() 來呈現字串版的物件內容。" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "ename": "TypeError", "evalue": "unsupported operand type(s) for +: 'int' and 'str'", "output_type": "error", "traceback": [ "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[1;32m<ipython-input-32-456c7e2c7a20>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[0mb\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;34m'8'\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[1;31m# 數值與字串相加結果未定義,如果沒有明確轉型,會出現 TypeError 的錯誤\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 4\u001b[1;33m \u001b[0ma\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mb\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[1;31mTypeError\u001b[0m: unsupported operand type(s) for +: 'int' and 'str'" ] } ], "source": [ "a = 3\n", "b = '8'\n", "# 數值與字串相加結果未定義,如果沒有明確轉型,會出現 TypeError 的錯誤\n", "a + b" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'[0, 1, 2, 3, 4, 5, 6]'" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "L = list(range(7))\n", "# 把 List 物件內容用字串表示\n", "str(L)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### § 物件參考 Object Reference\n", "\n", "兩個變數可以共享物件的參考。當變數 a 和 b 參考至同一個物件:\n", "- 對於可以就地變更元素內容的容器而言,修改 b 的元素內容,因為是同一份物件,a 的元素內容跟著變。\n", "- 若指定一個新的物件給其中一個變數,就算內容一模一樣,兩變數結果會是參考至不同物件。\n" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\"b == a\" True\n", "\"b is a\" True\n" ] } ], "source": [ "a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n", "b = a\n", "\n", "# \"==\"比較內容,\"is\"判斷是否為同一個物件參考,應該都會是 True\n", "print('\"b == a\"', b == a)\n", "print('\"b is a\"', b is a)" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\"b == a\" True\n", "\"b is a\" True\n" ] } ], "source": [ "# a 和 b 參考至同一物件\n", "a = b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n", "\n", "# 修改一個的元素內容,另一個會跟著變\n", "b[-1] = 11\n", "print('\"b == a\"', b == a)\n", "print('\"b is a\"', b is a)" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\"b == a\" True\n", "\"b is a\" False\n" ] } ], "source": [ "# a 和 b 參考至同一物件\n", "a = b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n", "\n", "# 指定相同內容的新物件給 b,兩變數的參考物件變成不同\n", "b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n", "print('\"b == a\"', b == a)\n", "print('\"b is a\"', b is a)" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\"b == a\" True\n", "\"b is a\" False\n" ] } ], "source": [ "# a 和 b 參考至同一物件\n", "a = b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n", "\n", "# 同樣是指定了新物件 - list經過索引返回的片段是新的物件\n", "b = a[:]\n", "print('\"b == a\"', b == a)\n", "print('\"b is a\"', b is a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "<a id=\"sequence-operations\"></a>\n", "\n", "## 2.4 序列容器的操作 Sequence Operations\n", "\n", "### § 索引規則 Indexing Rules\n", "- 在序列容器變數後,使用中括號內置索引序號,如:`S[3]`。\n", "- 序列第一個元素的索引序號為 `0`,往後面依次遞增。如:`S[0]`, `S[1]`, ..., `S[len(S) - 1]`。\n", "- 序列最後一個元素的索引序號為 `-1`,往前面依次遞減。如:`S[-1]`, `S[-2]`, ..., `S[-len(S)]`。\n", "- 可以使用的索引序號不能超過物件的元素個數減1。如:`S[len(S)]` Python會出現錯誤訊息。" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# List 是最常用的序列容器\n", "L = list(range(1, 10))\n", "(L[0] == L[-len(L)]) and (L[-1] == L[len(L) - 1])" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 字串是字元的序列\n", "s = str(L)\n", "(s[1] == '1') and (s[-2] == '9') and (s[1] < s[-2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### § 片段規則 Slicing Rules\n", "由序列容器中取出片段成為一個新的序列容器物件,可以取得的片段範圍僅限於合法的索引範圍。若指定的片段超過範圍,所產生的新序列容器只會包含合法範圍內的片段,Python不會發出錯誤訊息。片段範圍的指定一樣使用中括號,語法如下:\n", "\n", "<p style=\"text-align: center;font-weight:bold\">\n", " [ 起始序號 : 結束序號 : 遞增(減)量 ]\n", "</p>\n", "\n", "- 注意索引結果的元素,不包含結束序號的那個元素;也就是說 `[start : end]` 取的是 $[start, end)$ 的區間。\n", "\n", "| Slicing 的操作 | 說明 |\n", "|----------------|----------------------------------------------|\n", "| `S[1:3]` | 取元素範圍序號 1 到 2 |\n", "| `S[1:]` | 取元素範圍序號 1 到最後一個 |\n", "| `S[:-1]` | 取元素範圍第一個到最後一個的前一個 |\n", "| `S[:]` | 取所有範圍的元素 |\n", "| `S[2::3]` | 元素範圍序號 2 到最後一個,每遞增 3 個序號取 |\n", "| `S[::2]` | 所有元素的範圍內,從頭到尾每隔一個序號取 |\n", "| `S[::-1]` | 反向取所有範圍的元素 |\n", "| `S[-2:0:-1]` | 所有範圍的元素去頭尾,反向取 |" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1]" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# List slicing 練習\n", "L = list(range(1, 10))\n", "L[:-1] + L[::-1]" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[7, 8, 9, 8, 7, 6, 5, 4, 3, 2]" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# List slicing 練習\n", "L[6:] + L[-2:0:-1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### § 成員操作 Membership Operations\n", "| 成員的操作 | 說明 |\n", "|------------------------|------------------------------------------------------------------|\n", "| `x in S` | S 的成員裡有 x(只要值相同就算),結果為 `True` 或 `False` |\n", "| `x not in S` | S 的成員裡沒有 x ,結果為 `True` 或 `False` |\n", "| `for x in S:` | (迴圈)列舉 S 裡的成員到 x |\n" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 判斷是否存在成員\n", "L = list(range(10))\n", "(9 in L) and (10 not in L)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### § 卸載操作 Unpacking Operations\n", "當序列容器或可迭代(iterable)物件在等號(`=`, assignment)右邊,等號左邊如果有對應元素個數的變數,容器的元素內容會自動分派卸載。\n", "\n", "| 自動卸載 | 結果 |\n", "|----------------------------|------------------------|\n", "| `a, b, c = [1, 2, 3]` | a = 1, b = 2, c = 3 |\n", "| `a, b, c = (1, 2, 3)` | a = 1, b = 2, c = 3 |\n", "| `a, b, c = 1, 2, 3` | a = 1, b = 2, c = 3 |\n", "| `a, b, c = range(3)` | a = 0, b = 1, c = 2 |\n", "\n", "容器卸載是將每個元素拆到容器外,卸載操作通常用在卸載不同類型容器的內容到新容器,或容器內容卸載為叫用函式的參數。 一般可以列舉的、序列型態的容器、字典的 key 都用 `*` 操作,字典容器的 value 用 `**` 卸載。\n", "\n", "| 卸載操作 | 輸出 |\n", "|---------------------------------------------------------|------------------------|\n", "| `print(*range(4))` | 0 1 2 3 |\n", "| `*range(4),` | (0, 1, 2, 3) |\n", "| `[*range(4), 4]` | [0, 1, 2, 3, 4] |\n", "| `'unpack keys: {}, {}'.format(*{'a':1, 'c':3})` | 'unpack keys: a, c' |\n", "| `'unpack values: {a}, {c}'.format(**{'a':1, 'c':3})` | 'unpack values: 1, 3' |" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 2 3 4 5\n" ] } ], "source": [ "# 用在函式的呼叫,卸載到函式的參數\n", "print(*[1], *[2], 3, *[4, 5])" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 1, 2, 3, 4, 5, 6, 7]" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 用在將非同類型容器的內容卸載到新容器\n", "[*range(4), 4, *(5, 6, 7)]" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Coordinate System: latitude, longitude'" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 卸載 dict 的 key\n", "'Coordinate System: {}, {}'.format(*{'latitude': '37.24N', 'longitude': '-115.81W'})" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Coordinates: 37.24N, -115.81W'" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 卸載 dict 的 value\n", "'Coordinates: {latitude}, {longitude}'.format(**{'latitude': '37.24N', 'longitude': '-115.81W'})" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.8" } }, "nbformat": 4, "nbformat_minor": 2 }