{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "
\n",
" \n",
" Open In Jupyter nbviewer\n",
" \n",
" \n",
"
\n", " [ 起始序號 : 結束序號 : 遞增(減)量 ]\n", "
\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]` | 所有範圍的元素去頭尾,反向取 |\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### § 成員操作 Membership Operations\n", "\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": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1, 2, 3, 4, 5, 6, 7, 8, 9]\n" ] } ], "source": [ "# 用 range() 來幫忙產生整數列\n", "L = list(range(1, 10))\n", "print(L)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 4, 5, 6, 7, 8]" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 取開始到倒數第二個的區間\n", "L[:-1]" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[9, 8, 7, 6, 5, 4, 3, 2, 1]" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 反向取所有元素\n", "L[::-1]" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1]" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 兩個 list 相加結果就是做串接\n", "L[:-1] + L[::-1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "## 迴圈及流程控制 Loops and Control flow\n", "\n", "對於一般陳述句,Python 會一行一行往下執行,直到碰到改變流程的陳述句:\n", "\n", "+ `if-elif-else`: 條件陳述式,選擇性執行。\n", "+ `while`: 條件式迴圈,迭代執行。\n", "+ `for`: 序列式迴圈,迭代執行。\n", "\n", "條件或迴圈的語法,共同點是都在測試某個條件後,符合條件才會執行接續的區塊陳述。 Python 程式的語法中,區塊的程式碼使用 ***space*** 或 ***tab*** 縮排的層次來區隔不同執行條件的陳述句。\n", "\n", "+ `pass`: 佔位述句。\n", "+ `break`: 中斷。\n", "+ `continue`: 繼續。\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### § if-elif-else 條件陳述式\n", "\n", "`if-elif-else` 條件陳述式由一個 `if` 邏輯測試條件,中間可有可無的 `elif` 測試條件,以及最後也是可有可無的 `else` 條件所組成。 每個條件都有對應的陳述式區塊,在條件測試為 True 時會被執行。 一般的形式像:\n", "```\n", "if test1:\n", " statements1\n", "elif test2:\n", " statements2\n", "else:\n", " statements3\n", "```\n", "\n", "簡單的 if-else 指派陳述如:\n", "```\n", "if test:\n", " x = a\n", "else:\n", " x = b\n", "```\n", "可以簡化成一行**三元運算**的陳述句:\n", "```\n", "x = a if test else b\n", "```\n" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "neither good nor bad, x is excellent\n" ] } ], "source": [ "a, b = 'good', 'bad'\n", "\n", "# 試著改變 x = 'good', 或 x = 'bad' 看看條件測試的結果\n", "x = 'excellent'\n", "#x = 'good'\n", "#x = 'bad'\n", "\n", "if x == a:\n", " print('x is also good')\n", "elif x == b:\n", " print('x is bad')\n", "else:\n", " print('neither good nor bad, x is {}'.format(x))" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'good'" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 三元運算陳述句\n", "a if x != 'bad' else b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### § while 條件式迴圈\n", "\n", "`while` 迴圈包含了一個標頭的邏輯條件測試式,一個或多個縮排的區塊陳述式。\n", "\n", "```\n", "while test:\n", " statements\n", "```\n" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "excellent\n" ] } ], "source": [ "# 一個一個字元複製直到字串完全相等\n", "x = 'excellent'\n", "c = ''\n", "while c != x:\n", " c += x[len(c)]\n", "\n", "print(c)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "excellent\n", "excellen\n", "excelle\n", "excell\n", "excel\n", "exce\n", "exc\n", "ex\n", "e\n", "c = 0\n" ] } ], "source": [ "# 註: Python 的空字串會被視為是其他字串的子字串\n", "while c in x:\n", " print(c)\n", " if len(c) > 1:\n", " c = c[:-1]\n", " elif len(c) == 1:\n", " # 試看看 c = '0' 和 c = '' 的結果有甚麼不同?\n", " c = '0'\n", " else:\n", " break\n", "\n", "print('c =', c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### § for 序列式迴圈\n", "\n", "`for` 迴圈是一個通用的迭代器(iterator),可以用來走訪任何***序列容器的元素***或***可迭代(iterable)物件***。 `for` 迴圈區塊標頭從要走訪的 iterable_object 中循序指派內容物參考到 item,然後針對每個 item 重複執行區塊中的陳述句。\n", "\n", "```\n", "for item in iterable_object:\n", " statements\n", "```\n" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "e\n", "x\n", "c\n", "e\n", "l\n", "l\n", "e\n", "n\n", "t\n" ] } ], "source": [ "# 變數 c 不須事先宣告,若先前已經有值也不影響 for 迴圈的執行\n", "for c in x:\n", " print(c)" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "e\n", "x\n", "c\n", "e\n", "l\n", "l\n", "e\n", "n\n", "t\n" ] } ], "source": [ "for c in x:\n", " # 試看看在 '0123456789' 字串中加入任意一個 'e', 'x', 'c', 'l', 'n', 't' 的字元,結果有甚麼不同?\n", " if c not in '0123456789':\n", " print(c)\n", " else:\n", " break" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### § pass 佔位述句\n", "\n", "什麼事都沒作,通常只是為了暫時滿足語法規則,用來佔個位置的述句。 \n", "\n", "```\n", "while True:\n", " pass\n", "```" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "# 沒作甚麼事,單純占用 CPU 時間的迴圈\n", "for i in range(2**25):\n", " pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### § break 中斷\n", "\n", "跳離最近的 `for` 或 `while` 迴圈。\n" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n", "4\n", "5\n" ] } ], "source": [ "for i in range(10):\n", " if i > 5: break\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### § continue 繼續\n", "\n", "在迴圈中出現時,忽略以下所有述句,回到迴圈標頭繼續下一輪迴圈。\n" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "5\n", "6\n", "7\n", "8\n", "9\n" ] } ], "source": [ "n = list(range(10))\n", "for i in n:\n", " if i < 5: continue\n", " print(i)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "## Comprehension 語法\n", "\n", "- 操作 `list` 和 `dict` 容器時,Python 提供了強大的功能性語法,分別稱為 [***List Comprehensions***](https://www.python.org/dev/peps/pep-0202/) 與 [***Dict Comprehensions***](https://www.python.org/dev/peps/pep-0274/)。\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### § List Comprehensions\n", "\n", "對於序列容器或可迭代物件 S 進行操作,並生成一個新的 `list` 物件。\n", "\n", "| 成員的操作 | 說明 |\n", "|-----------------------------------|-------------------------------------------------------------------|\n", "| `[運算表示句 for x in S]` | 針對每個 S 的成員 x 做運算,運算結果生成新的 list 物件 |\n", "| `[運算表示句 for x in S if 條件]` | 針對每個***符合條件***的成員 x 做運算,運算結果生成新的 list 物件 |\n", "\n", "List comprehension 語法結構可組成相當豐富的條件式迭代運算\n", "\n", "```\n", "[運算表示句 for x1 in S1 if 條件1\n", " for x2 in S2 if 條件2 ...\n", " for xN in SN if 條件N]\n", "```\n" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[11, 12, 13, 14, 15]\n" ] } ], "source": [ "L = [1, 2, 3, 4, 5]\n", "\n", "# 使用 List Comprehension 生成新的 List 物件\n", "L = [x + 10 for x in L]\n", "print(L)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 4, 8, 12, 16]" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 條件式挑選部份成員作處理\n", "[n*2 for n in range(10) if n % 2 == 0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### § Dict Comprehensions\n", "\n", "對於可拆解出成對的 (key, value) 的序列容器或可迭代物件 S 進行操作,並生成一個新的 `dict` 物件。\n", "\n", "| 成員的操作 | 說明 |\n", "|--------------------------------------------|---------------------------------------------------------------|\n", "| `{key:value for (key,value) in S}` | 針對每個 S 的成員 x 做運算,運算結果生成新的 dict 物件 |\n", "| `{key:value for (key,value) in S if 條件}` | 針對每個***符合條件***的成員 x 做運算,運算結果生成新的 dict 物件 |\n", "\n", "Dict comprehension 語法結構也可組成相當豐富的條件式迭代運算,但需注意`dict`容器的 *key* 不能重複,若重複指定不同 value 給同一個 key,結果對應的 value 會是最後指定的值。\n", "\n", "```\n", "{key:value運算表示句 for x1 in S1 if 條件1\n", " for x2 in S2 if 條件2 ...\n", " for xN in SN if 條件N}\n", "```" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'a': 97, 'b': 98, 'c': 99}" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 可迭代物件生成 dict 物件\n", "{x: ord(x) for x in 'abc'}" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'0': 0, '2': 4, '4': 16, '6': 36, '8': 64}" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 條件式挑選部份成員作處理\n", "{str(x): x ** 2 for x in range(10) if x % 2 == 0}" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'a': 1, 'b': 2, 'c': 3}" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 需要兩組序列進行兩兩配對的操作時,可以使用內建函式 zip() 來幫忙\n", "{k: v for (k, v) in zip(['a', 'b', 'c'], [1, 2, 3])}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "## 函式 Functions\n", "\n", "- Python 標準函示庫包含了一些常用的[內建函式](https://docs.python.org/3/library/functions.html)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### § def 函式定義\n", "\n", "函式以 `def` 關鍵字及指定的函式名字開始,後面使用小括號接著函式運算需要的所有參數。 區塊陳述包含函式所需的運算,運算結果的值使用 `return` 述句返回,若未明確指定,預設返回值為 `None`。\n", "\n", "```\n", "def name(arg_name1,..., arg_nameN=value):\n", " statements\n", " return value\n", "```\n", "\n", "| 可用參數定義格式 | 格式說明 |\n", "|--------------------|-------------------------------------------|\n", "| `arg_name1` | 一般參數,以位置或名字匹配 |\n", "| `arg_nameN=value` | 同一般參數,明確指定預設值 |\n", "\n", "\n", "**函式呼叫**\n", "\n", "```\n", "name(arg_value1,... arg_nameN=value)\n", "```\n", "\n", "| 可用參數定義格式 | 格式說明 |\n", "|---------------------|------------------------------------------------|\n", "| `arg_value1` | 以位置匹配傳遞參數 |\n", "| `arg_name_N=value` | 以名字匹配傳遞參數 |\n" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "1\n" ] } ], "source": [ "# 定義一個函式 Add(): 印出輸入參數相加的結果\n", "def Add(a, b, c):\n", " print(a + b + c)\n", "\n", "# 函式呼叫與參數傳遞\n", "Add(2, 3, -4)\n", "\n", "# 以位置及名字匹配方式傳遞參數\n", "Add(2, c=-4, b=3)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "### § 參數傳遞的基本認識\n", "\n", "1. 參數的傳遞,是**物件的參考**複製給了函式的 local 變數名字; 意即函式***參數所指向物件與呼叫端是同一物件***。\n", "2. 在函式內,重新指派新的物件參考給參數變數名字,不會影響呼叫端。\n", "3. 如果參數物件是可就地變更的類別,在函式內異動物件內容,呼叫端也會跟着改變。\n", "\n", "在設計程式時,建議遵循以下原則:\n", "1. 在函式中,避免更改參數物件的元素內容。\n", "2. 如果有需要回傳運算結果,請利用 `return` 來回傳,讓呼叫端來決定是否覆蓋原物件內容。\n" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "b = 5 id = 140708456839104\n", "a = 5 id = 140708456839104\n", "a = 9 id = 140708456839232\n", "b = 5 id = 140708456839104\n" ] } ], "source": [ "# 指派新物件不影響呼叫端\n", "def f(a):\n", " # 一開始 a 與呼叫端的 b 參考同一物件\n", " print('a =', a, 'id =', id(a))\n", " # 指派新的 int 物件\n", " a = 9\n", " # 現在 a 參考到新物件\n", " print('a =', a, 'id =', id(a))\n", "\n", "b = 5\n", "# before function call\n", "print('b =', b, 'id =', id(b))\n", "\n", "f(b)\n", "\n", "# after function called\n", "print('b =', b, 'id =', id(b))" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "x = [2, 3] id = 2427060925824\n", "y = [4, 5, 6] id = 2427061789376\n", "L1 = [2, 3] id = 2427060925824\n", "L1 = [7, 8, 9] id = 2427062155904\n", "L2 = [4, 5, 6] id = 2427061789376\n", "L2 = ['changed', 5, 6] id = 2427061789376\n", "x = [2, 3] id = 2427060925824\n", "y = ['changed', 5, 6] id = 2427061789376\n" ] } ], "source": [ "# 可就地變更的類別,兩邊內容是同一份\n", "def f_list_args(L1, L2):\n", " print('L1 =', L1, 'id =', id(L1))\n", " # 指派新的 list 物件\n", " L1 = list(range(7, 10))\n", " print('L1 =', L1, 'id =', id(L1))\n", " \n", " print('L2 =', L2, 'id =', id(L2))\n", " # 不建議在函式中直接更改參數物件的元素內容。\n", " L2[0] = 'changed'\n", " print('L2 =', L2, 'id =', id(L2))\n", "\n", "\n", "x = [2, 3]\n", "y = [4, 5, 6]\n", "\n", "# before function call\n", "print('x =', x, 'id =', id(x))\n", "print('y =', y, 'id =', id(y))\n", "\n", "f_list_args(x, y)\n", "\n", "# after function called\n", "print('x =', x, 'id =', id(x))\n", "print('y =', y, 'id =', id(y))\n" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "vec = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] id = 2427061788864\n", "vec = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] id = 2427061772544\n" ] } ], "source": [ "# 有需要回傳運算結果就用 return,讓呼叫端自己決定覆蓋原物件內容。\n", "def min_max_scaler(vec_in):\n", " min_v = min(vec_in)\n", " max_v = max(vec_in)\n", " interval = max_v - min_v\n", " vec_out = [(float(v) - min_v) / interval for v in vec_in]\n", " return vec_out, interval\n", "\n", "vec = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]\n", "\n", "# before function call\n", "print('vec =', vec, 'id =', id(vec))\n", "\n", "vec, _ = min_max_scaler(vec)\n", "\n", "# after function called\n", "print('vec =', vec, 'id =', id(vec))" ] } ], "metadata": { "colab": { "authorship_tag": "ABX9TyOuIYEocvTI/XCQlqS6NQqx", "collapsed_sections": [], "name": "Python Quick Start.ipynb", "provenance": [] }, "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.5" } }, "nbformat": 4, "nbformat_minor": 1 }