跳至主要内容

用 Python 自學程式設計:程式設計思維入門

· 閱讀時間約 14 分鐘

Python 自學程式設計:程式設計思維入門

最近幾年全球刮起了一股爭相學習電腦科學(Computer Science)和程式設計(Programming)的風氣,上至總統、首相下至升斗小民都爭相開始學寫程式。事實上,學寫程式最重要的是學習電腦科學背後思考方式和邏輯,學習如何透過科技解決生活上的問題。更進一步說,程式設計與其說是一種科學,更偏向一種藝術人文的創作與科學的混合體。以前畫家或是作家是拿紙筆創作,現在只要有一部電腦,連上網路,就可以透過敲打鍵盤將自己的創意付諸實踐。

有人說:程式設計 = 演算法 + 資料結構

這樣的說法不能說錯。事實上,具備良好資料結構和演算法素養的程式設計師往往可以寫出品質較好的程式碼,但大部分人看到演算法和資料結構就已經滿臉問號了,更別提曾經在學校被這兩門課程心靈受挫的學生們。所以對於初學者來說,更應該讓他了解,事實上學程式設計思維就是在學習解決問題的能力:

  1. 尋找並發現問題
  2. 釐清並定義問題
  3. 分解問題
  4. 尋找解決方法和資源
  5. 驗證問題和解決方式

唯有具備這樣解決問題的能力,才能稱得上真正學會程式設計思維。而這樣的思考方式的訓練是不管將來到哪裡,是否有從事程式設計相關工作都受用,這才是對於學習電腦科學與程式設計思維正確的認知。

寫程式就是下指令請電腦做事情

剛剛我們在上面提到程式設計思維中有一個部分是分解問題,事實上,寫程式在定義問題後,我們必須把問題切分,就像是食譜一樣,不管是再豐盛的料理或是滿漢全席,都有一個個步驟去完成。舉例來說,我們今天要創作一道蔥花蛋或菜脯蛋,我的步驟會是:

  1. 放點油
  2. 打蛋
  3. 如果喜歡蔥花可以加入蔥花,如果喜歡菜脯可以加入菜脯(程式術語:if...else 條件判斷)
  4. 放入少許鹽巴
  5. 中火快炒,翻五次面(程式術語:for 迴圈)
  6. 當看到蛋面呈現金黃色時可以起鍋,結束料理(程式術語:while 迴圈)
  7. 好吃的蔥花蛋或菜脯蛋上桌

再大程式切分後就變成一個個小程式和指令,將程式切分成一個個模組,再將它們都組裝起來就成我們的應用程式和系統。

第一次學寫程式,學哪一種語言好呢?

既然程式設計思維很重要,究竟第一次學寫程式,學哪一種語言好呢?

先講結論:Python 語法平易近人,學習曲線平緩,應用廣,可以很快做出一些解決生活上問題的應用,累積成就感,適合初學者。當然若你是國中小的學生,Scratch 之類的拖拉式圖象化程式語言或許是合適選擇,但成人一般對於這種玩具比較排斥些,認為不是真正在學寫程式。

一般而言除了區分高低階程式語言外,我們會把程式語言分為:

靜態語言:在程式語言中我們會使用變數(variable)儲存程式的值,在靜態語言中需要事先宣告變數型態(type),也宣告了它會在記憶體中佔有多少空間等資訊。電腦會透過這些資訊把程式編譯(compile)成低階的機器語言讓電腦可以執行。這樣的設計可以讓電腦執行起來更有效率,但對於開發者來說會比較繁瑣一些(例如:宣告字串變數要在變數前加 string 宣告),也由於類型被宣告後無法改變,所以被稱為靜態語言。常見的靜態語言包括:C/C++、Java、C#、Go、Swift 等)。

動態語言(又稱為 script language):相對於靜態語言,動態語言不會強制變數類型宣告,它不是使用編譯器而是使用直譯器(interpreter)來解譯。動態語言雖然開發和撰寫程式上效率較快,但執行速度往往比靜態語言慢(現在差距已經慢慢變小)。一般常見的動態語言包括:Python、JavaScript、PHP、Ruby 等)。

以下就來先簡單介紹常見程式語言和它的簡單語法範例(可以透過 repl.it 可以將程式碼貼在網頁上呈現所見即所得效果):

  1. Python 本系列文章的主角,Python 是一種物件導向、直譯式的跨平台動態程式語言,它包含了一組功能完備的標準庫和豐富套件生態系,可以輕鬆完成很多常見的任務(例如:物聯網應用開發、遊戲、讀寫檔案、自然語言處理、網路爬蟲、網站開發、機器學習等),因為它可以很輕易整合其他底層語言,所以又稱為膠水語言。它的語法簡單,與其它大多數程式設計語言使用大括弧不一樣,它使用縮進來定義語句塊。由於具備簡潔易學等特性,是許多開發者推薦 Python 為初學者第一個學習的程式語言。由於版本更迭,我們接下來討論的主要是以 Python3 為主。以下是使用 Python 印出最喜歡的語言:

    language = 'Python'
    print('My favorite Language is {}'.format(language))
  2. C 經典的傳統主力程式語言,適用於需要效能重視速度的應用,可以操作許多小細節,但學習門檻稍微高一些,執行前需要事先編譯完成:

    #include <stdio.h>
    int main(int atgc, char *argv[]) {
    string language = "C++";
    printf("My favorite Language is %s", language);
    return 0;
    }
  3. C++ 屬於 C 家族成員,具備物件導向特性,同樣是適用於需要效能重視速度和操作底層韌體、硬體的好選擇:

    #include <iostream>
    using namespace std;
    int main() {
    string language = "C++";
    cout << "My favorite Language is " << language;
    return(0);
    }
  4. Java 常見於企業系統和 Android 行動應用開發的 Java 是物件導向程式語言,由於跨平台開發等特性讓 Java 一直是市場蠻熱門的語言。

    public class CodeLanguage {
    public static void main(String[] args) {
    string language = "Java";
    System.out.format("My favorite Language is %s", language);
    }
    }
  5. C# 由微軟推出吸收了 C++/Java 等優點的物件導向程式語言,常見於開發微軟平台相關的應用程式。

    using System;
    namespace CodeLanguage {
    class CodeLanguage {
    static void Main() {
    string language = "C#";
    Console.WriteLine("My favorite Language is {}", language);
    }
    }
    }
  6. JavaScript 隨著版本演進和 Node.js 的推出後從玩具語言到可以挑大樑的程式語言,應用範圍遍及網頁前後端開發、遊戲開發、物聯網程式開發、手機程式開發等。是程式設計師社群平台 Github 和程式問答平台 StackOverflow 上最受歡迎的程式語言之一。且由於應用範圍廣泛,程式江湖更傳言:可以使用 JavaScript 編寫的程式,最終都會出現 JavaScript 版本。

    var language = 'JavaScript'
    console.log('My My favorite Language is ' + language);
  7. PHP 吸收了 C/Java/Perl 特點的網站開發主力語言,世界上有許多的網站都是使用 PHP 進行開發。

    <?php
    $language = 'PHP';
    echo 'My favorite Language is ' + language;
    ?>
  8. Ruby 常見於網頁 Web 開發,以 Ruby on Rails Web 開發框架聞名於程式設計社群。

    language = 'Ruby'
    puts 'My favorite Language is #{language}'
  9. Swift 由 Apple 推出的推出的程式語言,主要用於開發 iOS/Mac 系列產品,應用範圍也涉及到了伺服器端開發(Server)。

    let language = 'Swift'
    print("My favorite Language is ", language)

  10. Go 由 Google 推出的程式語言,適合用於平行化程式開發。

    package main
    import "fmt"

    func main() {
    language := 'Go'
    fmt.Printf("My favorite Language is %s", language)
    }

看完了眾多語言是不是發現其實 Python 語法還蠻可愛平易近人的呢?事實上,世界上沒有最好的程式語言,只有最適合的使用地方。接下來我們將透過 Python 學習程式設計思維。

Python 環境建置

在開始之前我們必須先建置相關的開發環境,讓自己從麻瓜(不會寫程式的人)變成擁有程式魔力的魔法師。

所謂工欲善其事,必先利其器,要開發好的應用程式必須先準備好開發環境才行。以下介紹我們在接下來開發 Python Flask Web 應用程式所需要安裝的開發環境工具(以下以 Mac OS 等 Unix-like 作業系統為示範,若是 Windows 使用者建議安裝 Virtualbox 並運行 Linux Ubuntu 作業系統,參考安裝文件):

  1. Microsoft VSCode 編輯器 Microsoft VSCode 是 Microsoft 推出的編輯器(非整合開發環境 IDE),夾帶著 Microsoft 過去打造 Visual studio 整合開發環境的豐富經驗,相比 Sublime Text 和其他編輯器,VSCode 的優勢在於開源且活躍的開發社群、內建 debugger 框架、原生 Git 整合、套件整合容易等特性。所以對於初學者來說 VSCode 是一個蠻適合入門的開發環境。它的安裝方式也十分簡易,在官網下載後按照指示安裝完成即可。

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    我們可以安裝 Python 語法和格式檢查的相關 Python 套件幫助除錯:

    Python Web Flask 實戰開發教學 - 簡介與環境建置

  2. 終端機環境(iTterm/內建 terminal) terminal(終端機)是我們下指令的地方,許多時候我們進行程式開發時不會使用 GUI 的介面而是使用下指令方式請電腦做相對應的行為。在 Linux 和 Mac 裡面都有內建的 terminal 的應用程式,若你是 Mac 用戶想使用更便利的工具(分割視窗、熱鍵、搜尋、自動補完等)可以額外安裝 iterm2 做使用。若是不想使用 Virtualbox,使用 Windows 讀者可以使用 Cmder 這個軟體當做終端機環境。

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    下指令($ 為提示字元,不用輸入):

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    對於有志於從事程式開發相關工作的讀者建議可以多熟悉指令碼的輸入,更多指令碼可以參考鳥哥撰寫的 Linux 基本指令介紹Linux 學習資源

  3. Git 版本控制系統/註冊 GitHub 帳戶 Git 是一種分散式版本控制系統,可以讓我們可以更方便地管理我們的程式碼。在網路上有非常多優秀的 Git 教學文件(連猴子都能懂的Git入門指南寫給大家的 Git 教學初心者 Git 上手攻略)。安裝 Git 方式是到官網下載軟體,依照指示安裝。

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    互動式語法學習:

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    在介紹完 git 之後我們來了解一下 GitHub。GitHub 是一個可以存放 git 程式碼專案的平台,透過 GitHub 我們可以接觸到最新的開放原始碼資訊,也可以將我們的程式碼開源出來。

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    從 GitHub 上複製程式碼

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    # 複製一份到本地端
    $ git clone https://github.com/happycoderorg/flask101.git
    # 移動到資料夾
    $ cd flask101

    常見 Git 指令:

    # 初始化專案
    $ git init
    # 查看狀態
    $ git status
    # 檢查差異
    $ git diff
    # 將變更檔案放入暫存區
    $ git add index.py
    # 使用 commit -m 提交變更
    $ git -a -m 'init commit'
    # 查看歷史
    $ git log
    # 放棄已經 commit 的檔案重回暫存區
    $ git reset HEAD index.py
    # 放棄檔案變更
    $ git checkout index.py
  4. Anaconda Python3 版本 Anaconda 是一個 all-in-one 的 Python 開發環境,對於初學者來說是個十分合適的開發環境包。Anaconda 具備了幾項特點:

    • 便於安裝許多流行的科學、數學、工程、數據分析的 Python 模組
    • 開源和免費
    • 跨平台支持:Linux、Windows、Mac
    • 支持 Python 版本切換,方便建立不同的虛擬開發環境
    • 內建 Spyder 編輯器和 Jupyter Notebook 環境

    安裝流程也十分簡單,進入 Anaconda 首頁,選擇對應作業系統(這邊使用 Mac OS): Python Web Flask 實戰開發教學 - 簡介與環境建置

    選擇對應 Python 版本下載,我們使用 Graphical Installer(圖像介面安裝方式),接著在下載完成時按照預設的安裝方式完成安裝; Python Web Flask 實戰開發教學 - 簡介與環境建置

    若是完整安裝成功,可以打開終端機輸入,若是顯示 Python 3.6.0 :: Anaconda 4.3.0 (x86_64) 版本號即安裝成功:

    $ python -V
    Python 3.6.0 :: Anaconda 4.3.0 (x86_64)

    接著要建立我們專案虛擬環境,這樣在安裝操作套件時比較不容易被污染到 root 的環境,啟動後會出現(套件名稱)的提示字元:

    # 顯示目前虛擬環境列表
    $ conda info -e
    # 創建虛擬環境
    $ conda create -n 套件名稱 python=3.6
    # 進入虛擬環境(若是 Windows cmder 環境不用加 source) ,成功後提示字元變成:(套件名稱)$
    $ source activate 套件名稱
    # 離開虛擬環境(若是 Windows cmder 環境不用加 source)
    $ source deactivate

建立虛擬環境

在建立相關開發工具後我們正式來建立一個 Python 的專案:

打開終端機移動到桌面,建立專案資料夾

$ cd ~/Desktop
$ mkdir python_examples
$ cd python_examples

建立獨立虛擬環境,並進入虛擬環境:

$ conda create -n python_examples_venv python
$ source activate python_examples_venv

成功進入虛擬環境後

你的第一個 Python 程式

一般而言我們會使用編輯器或是整合開發環境(IDE)進行程式撰寫,然後在終端機下指令執行程式。當然你也可以在終端機上使用內建互動式介面或是 jupyter notebook 進行。以下是我們要介紹給大家的簡單範例,第一個是隨機印出不同的喜愛程式語言,第二個是使用第三方套件擷取政府公開資料。程式設計唯有動手實際操作和實踐才能學的好,希望讀者打開你的編輯器透過自己實作去熟悉 Python 程式撰寫:

隨機印出不同的喜愛程式語言:

  1. 引入 random 套件
  2. 定義 language 變數,並將儲存程式語言字串的串列(list)資料結構給定給變數
  3. 產生 1 到 2 之間的隨機整數
  4. 列印出最喜歡的程式語言字串(含根據隨機產生的 index 選取到的串列值)
import random

language = ['Python', 'JavaScript', 'Java']
rnd = random.randint(1, 2)
print('My favorite Language is' + language[rnd])

可以在終端機移動到檔案資料夾執行程式檔案,例如:

python favorite_language.py

使用第三方套件擷取政府公開資料:

  1. 引入 requests 套件
  2. 爬取政府公開 Wifi 熱點資料,將取得資料回應給定給 response 變數
  3. 將資料轉換成以 { "key": "value "} 形式的 json 格式
  4. 印出取得的資料
import requests

url = 'http://data.taipei/opendata/datalist/apiAccess?scope=resourceAquire&rid=b087af42-2c54-4dbf-86c8-427d788779e5'
response = requests.get(url)
data = response.json()
print(data)

總結

以上就是程式設計思維入門簡介,透過了解什麼是程式設計思維和不同語言的特性,我們將對於自學程式設計有更正確的認識。接下來我們將透過 Python 介紹程式設計的內涵和不同的應用情境。當然,網路上也有許多學習資源可以當做參考,若你需要先建立基本的電腦科學知識的話,可以參考哈佛大學的熱門公開課程 CS50

(image via mshcdn

延伸閱讀

  1. Python 官網
  2. JavaScript 程式設計新手村
  3. Python Web 程式設計入門實戰
  4. 非本科生,我想半路出家學寫程式,該如何開始?
  5. 自學程式設計學習資源懶人包
  6. CS50
  7. CS50 TV

Go Web 程式設計入門教學:Web 基礎

· 閱讀時間約 4 分鐘

Go Web 程式設計入門教學

前面幾個單元中我們介紹了許多 [Go 程式語言](https://en.wikipedia.org/wiki/Go_(programming_language) 的基本語法,讓我們了解了 Go 程式語言的用法。接下來我們將透過 Go 來架設簡單的 Web Server。

Web 基本工作流程

Go Web 程式設計入門教學

在我們平常透過瀏覽器(Browser)瀏覽網站時,其背後事實上進行了一連串 Client 客戶端和 Server 伺服器端的互動,以下介紹 Web Server 工作流程簡介:

  1. 使用者在瀏覽器(Browser)網址列輸入 URL,瀏覽器會透過 DNS 伺服器進行解析,取得 Domain 對應伺服器(Server)的 IP 位置
  2. 找到對應 Server IP 後,Client 透過 TCP/IP 協定建立到 Server 的 TCP 連接
  3. Client 向 Server 發送 http 協定請求(request)封包,請求 server 資料
  4. 若請求資源中有動態網站的內容,Server 端會先呼叫伺服器端的程式語言解譯引擎負責處理內容。Server 將組好的內容向 Client 發送 http 協定回應(response)封包
  5. Client 和 Server 中斷 TCP 連線,等待下一次請求。由 Client 解析收到的回應(response)封包內容(body),在瀏覽器繪製 HTML/CSS/JavaScript 檔案內容

Go Web 程式設計入門教學

  • URL 解析

一般 URL(Uniform Resource Locator)結構大概長這樣:

Scheme://host{:port#}/path/.../[?query-string][#anchor]
  1. scheme:底層使用的協定(例如:https、http 或 ftp 等)
  2. host:http 伺服器 ip 位置或 domain
  3. port:http 預設是 80 可以省略,如果是使用其他則需要填寫,可以想成是 ip 的名牌號碼
  4. path:資源路徑
  5. query-string:使用 get 傳送的參數
  6. anchor:記錄超連結錨點
  • DNS(Domain Name System)解析路徑

    1. 輸入網址,查找本機的 host 檔案
    2. 若 host 沒有 domain/ip 對應,則查找本機的 DNS 解析器快取
    3. 若 host/本機 DNS 快取都沒有 domain 對應則解析 TCP/IP 參數中設定的第一個 DNS 伺服器或其快取回傳(不具權威性)
    4. 若都故障,則會由 domain 右往左查找對應 DNS 伺服器(轉發/非轉發模式),回傳給本機 DNS 伺服器
  • HTTP request 請求解析 接著我們聊聊在 HTTP 協定中有定義許多和伺服器互動的方式,最基本的有四種:GETPOSTPUTDELETE,分別對應資源的查增更刪,最常見的舊是 GETPOST

    其中 GET 會把傳送資料放在網址後面,資料為明碼且有長度限制,一般用於查找資料。而 POST 資料傳遞主要是放在 http request 的 body 中,所以新增資料或是傳遞較敏感資料通常會用 POST 傳送

  • HTTP response 回應解析 http response 封包組成由版本編號、狀態碼、狀態訊息組成

    HTTP 狀態碼是使用三位數字組成,在 HTTP/1.1 中定義五大類狀態碼:

    1XX 提示訊息 2XX 成功 3XX 重新導向 4XX client 錯誤 5XX server 錯誤

使用 Go 架設基本 Web Server

在 Go 中可以使用 net/http 套件建立 Web 伺服器:

  1. Request:使用者請求的資訊,包含 post, get, cookie 等
  2. Response:伺服器需要回饋給使用者的資訊
  3. Conn:使用者請求每次產生連結
  4. Handler:處理請求和產生傳回資訊的處理邏輯
package main

import (
"fmt"
"net/http"
"log"
)

// 處理函式
func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello world!")
}

func main() {
// 網址對應處理函式
http.HandleFunc("/", helloHandler)
// 監聽通訊 port
err := http.ListenAndServe(":7777", nil)
if err != nil {
log.Fatal("ListenAndServe", err)
} else {
log.Println("listen 7777")
}
}

總結

以上就是關於 Go 程式語言的 Web 基礎和 http 協定簡介,接下來的文章我們將透過 Golang Web 程式設計來學習 Go 這個程式語言的方方面面。

參考文件

  1. A tour of go
  2. Go Tutorial
  3. Go by Example
  4. Go Programming Language: An Introductory Tutorial
  5. Go tour Exercise
  6. Ubuntu Go install

(image via slidesharecdnwebsiteoptimization

Go Web 程式設計入門教學:語法基礎之函式(function)篇

· 閱讀時間約 4 分鐘

Go Web 程式設計入門教學

前面單元我們介紹了如何使用流程控制改變我們的程式執行順序,接下來的單元我們將透過 Golang Web 程式設計來學習 Go 這個程式語言。而在這個單元中我們將介紹 Go 函式的使用。程式語言唯有動手作才能學的好,你可以參考之前的文章建置開發環境或是使用線上開發環境進行學習。

函式簡介

有經驗的程式設計都知道程式撰寫的維護性很重要,其中模組化就是很重要的元素。當我們有一組程式出現過兩三次,那就很適合把它當做函式包裝起來。在程式語言中函式和數學上的函數有蠻多類似之處。我們可以把函式想成是一個黑盒子,透過呼叫函式可以完成我們想要做的工作,可能是傳入參數相加或是執行某段沒有回傳值的程式碼。

// 有一個關鍵字 func 其後接函式命名,可以傳入參數名稱和其資料型別(也可以不傳參數),後面是帶若有回傳值時的回傳值名稱和資料型別(也可以沒有回傳值)
func funcName(input1 type1, input2 type2) (output1 type1, output2 type2) {
// 若有回傳值
return value1, value2
}
  1. 基本函式 基本款的函式就是有函式名稱,傳入參數和回傳值:

    package main

    import "fmt"

    func add(a, b int) int { // 當只傳一個回傳值且沒有定義回傳值變數時可以簡化括號
    return a + b
    }

    func main() {
    fmt.Println(add(1, 2))
    }
  2. 多回傳值

    package main

    import "fmt"

    func addAndProduct(a, b int) (int, int) { // 多回傳值要用括號括起
    return a + b, a * b
    }

    func main() {
    fmt.Println(addAndProduct(1, 2))
    }
  3. 長度不固定參數

    func argFunc(arg ...int) {}
  4. 傳值與傳指標
    一般來說我們傳入函式的參數是複製一份傳入,改動參數不會影響原有值。若今天我們傳入的不是複製值而是記憶體位置的指標,則會更改到原有值。

    package main

    import "fmt"

    func add(a int) int {
    return a + 10
    }

    func main() {
    a := 1
    fmt.Println(add(a)) // 11
    fmt.Println(a) // 1
    }

    換傳指標進去:

    package main

    import "fmt"

    func add(a *int) int {
    *a = *a + 10
    return *a
    }

    func main() {
    a := 1
    fmt.Println(add(&a)) // 11
    fmt.Println(a) // 11
    }
  5. defer 採用後進先出方式在函式全部執行結束前執行,常用於開啟資源後關閉檔案:

    func ReadFile() bool {
    file.Open("./file.txt")
    defer file.Close()
    if failureA {
    return false
    }
    if failureB {
    return false
    }
    return true
    }
  6. 函式當做值和類型

    type test func(int) (bool)

    func testIt(f test, a int) {

    }
  7. Panic、Recover 中斷程式進入 panic 狀態,用 Recover 可以恢復

模組

  1. main 函式和 init 函式

    當程式很複雜時,可以拆成不同 package 和檔案,其中 package main 為必要,其於 package 可以放置其他函式,在 Go 中函式或變數開頭大寫代表公有露出可以讓其他套件使用,反之為私有。其中 main 和 init 是保留函式,init 函式可以用於所有 package,main 用於 package main。Go 語言會自動呼叫兩者,init 是可選的,程式初始化是從 main 開始,如果有匯入其他套件會在編譯時依序匯入。如果有一個套件被引入多次,只會被引入一次。

    相對路徑:

    import "./model" // 同一目錄的 model 下

    絕對路徑:

    import "xxx/model" // gopath/src/xxx/model

    一般引用套件用法:

    import (
    "fmt"
    )

    fmt.Println("hi")

    點用法:

    import (
    . "fmt"
    )

    Println("hi")

    別名:

    import (
    f "fmt"
    )

    f.Println("hi")

    只執行套件中 init,不使用裡面函式:

    import (
    _ "fmt"
    )

總結

以上就是關於 Go 程式語言的基本語法中流程控制介紹,接下來的文章我們將透過 Golang Web 程式設計來學習 Go 這個程式語言的方方面面。

參考文件

  1. A tour of go
  2. Go Tutorial
  3. Go by Example
  4. Go Programming Language: An Introductory Tutorial
  5. Go tour Exercise
  6. Ubuntu Go install
  7. 從Go看現代程式語言

(image via cuelogic

Go Web 程式設計入門教學:語法基礎之流程控制(flow control)篇

· 閱讀時間約 4 分鐘

Go Web 程式設計入門教學

前面單元我們介紹了如何建置 Go 變數和資料型別的使用,接下來的單元我們將透過 Golang Web 程式設計來學習 Go 這個程式語言。而在這個單元中我們將介紹 Go 的流程控制的使用。程式語言唯有動手作才能學的好,你可以參考之前的文章建置開發環境或是使用線上開發環境進行學習。

流程控制簡介

一般而言,程式語言是由上往下執行,若我們需要程式依照我們設計的邏輯方向執行就需要流程控制的協助。在這邊主要談的流程控制有三部分:條件判斷、迴圈循環、跳躍控制。

我們使用制做菜脯蛋食譜步驟來講解範例:

  1. 放點油
  2. 打蛋
  3. 如果喜歡蔥花可以加入蔥花,如果喜歡菜脯可以加入菜脯(程式術語:if...else 條件判斷)
  4. 放入少許鹽巴
  5. 中火快炒,翻五次面(程式術語:for 迴圈)
  6. 當看到蛋面呈現金黃色時可以起鍋,結束料理(程式術語:while 迴圈)
  7. 好吃的蔥花蛋或菜脯蛋上桌

首先介紹,條件判斷,如果 if...。條件判斷是一種邏輯判斷,當符合條件就怎麼樣,不符合條件就怎麼樣。

  1. if...else

    package main

    import "fmt"

    var taste = "菜脯蛋" // 喜歡菜脯蛋

    if taste == "菜脯蛋" {
    fmt.Println("加入菜脯")
    } else {
    fmt.Println("加入蔥花")
    }

    Go 語言中除了條件判斷不用加 () 外,也可以在條件判斷敘述宣告變數,但只會存活於條件邏輯區塊使用上。

    package main

    import "fmt"

    if taste := "蔥花蛋"; taste == "菜脯蛋" {
    fmt.Println("加入菜脯")
    } else {
    fmt.Println("加入蔥花")
    }

    fmt.Println(taste) // 編譯錯誤,條件判斷敘述宣告的變數,只會存活於條件邏輯區塊使用上
  2. goto Go 中還提供了 goto 語法,讓你可以直接跳躍到某定義區塊,但建議小心使用。

    package main

    import "fmt"

    func main() {
    num := 91

    if num >= 60 {
    fmt.Println("hi true")
    goto PASS
    } else {
    fmt.Println("hi false")
    }
    PASS:
    fmt.Println("hi pass")
    }
  3. for 迴圈 在 go 中 for 迴圈的功能強大,既可以被當做循環讀取資料,又可以當做 while 來控制邏輯,還能反覆操作運算,以下介紹 for 語法:

    for 變數宣告或函式回傳值; 條件判斷; 每輪結束時操作 {
    // ...
    }

    我們接著使用食譜範例,中火快炒,翻五次面:

    package main

    import "fmt"

    func main() {
    for index := 0; index < 5; index++ {
    fmt.Println("翻面", index + 1, "次")
    }
    }

    當我們不知道具體要迴圈幾次時可以使用 while,但由於 Go 中沒有 while 關鍵字,當忽略了 ;,就可以當 while 迴圈使用:

    package main

    import "fmt"

    // 從 1 加到 10
    func main() {
    sum := 0
    i := 0
    for i <= 10 {
    sum += i
    i++
    }
    fmt.Println(sum)
    }

    使用 break 和 continue 可以跳出整個循環和跳過當下:

    package main

    import "fmt"

    // 從 1 加到 10
    func main() {
    sum := 0
    i := 0
    for i <= 10 {
    if i == 3 {
    break; // continue 跳過 3,break 到 3 整個循環跳出
    }
    sum += i
    i++
    }
    fmt.Println(sum)
    }

    善用 for 也可以把 slicemap 資料一一取出:

    package main

    import "fmt"

    for key, value := range map { // 也可以忽略其中一值,for _, value := range map
    fmt.Println(key, value)
    }
  4. switch 當我們需要寫很多 if...else 時就是使用 switch 的好時機:

    package main

    import "fmt"

    func main() {
    i := 2
    switch i {
    case 1:
    fmt.Println("hello:", i) // go 中不用加 break 會自己跳出不會往下執行
    case 2:
    fmt.Println("hello:", i) // 加上 fallthrough 可以強制往下執行
    fallthrough
    default:
    fmt.Println("hello: default")
    }
    }

總結

以上就是關於 Go 程式語言的基本語法中流程控制介紹,接下來的文章我們將透過 Golang Web 程式設計來學習 Go 這個程式語言的方方面面。

參考文件

  1. A tour of go
  2. Go Tutorial
  3. Go by Example
  4. Go Programming Language: An Introductory Tutorial
  5. Go tour Exercise
  6. Ubuntu Go install
  7. 從Go看現代程式語言

(image via cuelogic

Go Web 程式設計入門教學:語法基礎之變數(variable)和資料型別(type)篇

· 閱讀時間約 5 分鐘

Go Web 程式設計入門教學

前面單元我們介紹了如何建置 Go 開發環境,接下來的單元我們將透過 Golang Web 程式設計來學習 Go 這個程式語言。而在這個單元中我們將介紹 Go 的變數和常數宣告以及資料型別的使用。程式語言唯有動手作才能學的好,你可以參考之前的文章建置開發環境或是使用線上開發環境進行學習。

定義變數和使用

變數是程式語言中暫存資料的盒子,在 Go 中比較特別的是定義變數有多種方式(特別的是 Go 語言和 C 語言在設計上比較不同的地方是 Go 語言把變數型別宣告放在變數名稱後面),以下列出比較常見的變數使用方式:

  1. 一般變數宣告

    // var 關鍵字 變數名稱 資料型別
    var varName type

    範例:

    var str string
  2. 定義多個變數

    var var1Name, varName2 type

    範例:

    var str1, str2 string
  3. 定義變數並初始化

    var varName type = value
  4. 同時初始化多個變數

    var varName1, varName2, varName3 type = v1, v2, v3
  5. 簡化宣告

    var varName1. varName2, varName3 = v1, v2, v3

    另外一種是使用 := 符號取代 vartype,但要注意的是這樣的方式只能在函式內部使用,若是在全域使用會出現編譯錯誤,一般使用 var 定義全域變數。它的變數生命週期為 block 內。

    package main

    import "fmt"

    var num = 10

    // 編譯錯誤
    str0 := "world"

    func main() {
    var str1 = "hello"
    str2 := "world"
    fmt.Println(num)
    fmt.Println(str1)
    fmt.Println(str2)
    if true {
    var str3 = "XD" // str3 := "XD"
    fmt.Println(num)
    fmt.Println(str1)
    fmt.Println(str2)
    fmt.Println(str3)
    }
    fmt.Println(num)
    fmt.Println(str1)
    fmt.Println(str2)
    // 變數生命週期結束 undefined 錯誤
    fmt.Println(str3)
    }

    值得注意的若是在函式內宣告但沒使用會出現編譯錯誤:

    package main

    import "fmt"

    var num = 10

    func main() {
    var str = "hello"
    fmt.Println(str)
    }
    ./main.go:10:6: str declared and not used

定義常數

常數和變數不同是在編譯時就確認值,在程式執行期間不可以更改值。在 Go 程式語言使用 const 定義常數,其語法如下:

const constName = value
const Pi = 3.14
const Name string = "Mark"

內建簡單資料型別

  1. 布林值 在 Go 布林值是 truefalse,預設為 false

    var isActived = true
  2. 數字 在 Go 語言中主要分為 intuint 兩類型數字資料型別,個別之間還有位元可以做選擇,例如:int32。注意兩種數字資料型別不能互相設定或操作(例如:相加)

    var num = 12
  3. 字串 Go 語言中使用 UTF-8 字元編碼,使用 "" 來包裹字串:

    var str string = "hello"
    str[1] // e

    ch = []byte(str)
    ch[1] = 'w'
    str2 = string(ch)
    fmt.Println(str2) // hwllo
  4. 錯誤類型 在 Go 語言中有一個 error 類型,在套件中也有個 errors 負責處理錯誤訊息:

    import errors
    err := errors.New("throw error")

    if err != nil {
    fmt.Println(err)
    }

複雜資料型別

  1. array array 就是一般程式語言的陣列,基本上和其他程式語言相同:

    // 變數名稱 [長度]類別
    var arrayName [n]type

    陣列長度宣告後不能改變,傳入函式為副本,若需要傳指標進去可以使用 slice。實際使用方式:

    // 宣告長度為 10 類型為 int 的陣列
    var arr [10]int
    arr[0] = 7
    arr[1] = 13

    a := [3]int{1, 2, 3}
    b := [10]int{1, 2, 3}
    // 自動計算元素長度
    c := [...]int{1, 2, 3}
    // 二維陣列
    dArry := [2][4]{[3]{1, 2, 3}, [3]{2, 3, 4}}
  2. slice 有時候我們不會一開始就知道需要宣告多長的陣列,這時就需要使用動態陣列(是一個參考類型,總是指向底層 array):slice,其使用方式:

    var sliceName = []type

    實際使用:

    slice = []byte{1, 3, 4}
    array = [3]int{1, 3, 4}
    bySlice :=
  3. map map 和其他程式語言的 dict 和 hash map 相似,使用方式:

    var mapName = map[keyType]valueType

    key 可以是除了 int 外其他類型,取值使用 key 取值:

    // 第一種宣告方式
    var numbers map[string] int
    // 第二種宣告方式
    numbers := make(map[string]int)
    numbers["one"] = 1
    numbers["two"] = 7
    numbers["three"] = 13
    fmt.Println("three", numbers["three"])

    // key 數量
    m := map[string]int {"1": 1, "3": 2}
    fmt.Println(len(m))

    // map 新增、刪除、修改、查找
    numbers["three"] = 13
    value, ok := numbers["three"]
    numbers["three"] = 17
    delete(numbers["three"])

    此外 map 是無序的,也是個參考類型指到底層:

    numbers := make(map[string]int)

    numbers["three"] = 13
    numbers2 := numbers
    numbers2["three"] = 1 // numbers["three"] 也變成 1

make、new 比較

make 一般用於內建資料型別(map、slice 和 channel)的記憶體分配,而 new 用於各種類型記憶體分配。make 回傳有初值的 T 類型,而 new 回傳指標。

總結

以上就是關於 Go 程式語言的基本語法中的變數和資料型別介紹,接下來的文章我們將透過 Golang Web 程式設計來學習 Go 這個程式語言的方方面面。

參考文件

  1. A tour of go
  2. Go Tutorial
  3. Go by Example
  4. Go Programming Language: An Introductory Tutorial
  5. Go tour Exercise
  6. Ubuntu Go install
  7. 從Go看現代程式語言

(image via cuelogic

Go Web 程式設計入門教學:基礎介紹與環境建置

· 閱讀時間約 4 分鐘

Go Web 程式設計入門教學

[Go 程式語言](https://en.wikipedia.org/wiki/Go_(programming_language) 是 Google 推出的靜態程式語言,其特色在於核心語法和關鍵字非常精簡(全部只有 25 個關鍵字!)並擷取了靜態語言的效能和動態語言的開發效率的優點,具備垃圾回收、快速編譯等特性,且針對平行化程式設計在使用上非常方便。接下來的文章我們將透過 Golang Web 程式設計來學習 Go 這個程式語言。程式語言唯有動手作才能學的好,你可以參考本篇文章建置開發環境或是使用線上開發環境進行學習。

Go 環境建置

安裝方式:

  1. 官網套裝安裝,線上也有官方提供的 playground 線上執行環境可以使用

  2. 使用套件管理工具 homebrew(mac)、apt-get(linux) 等進行安裝

    例如,在 linux 上安裝:

    $ sudo apt-get install golang-go

    或是主動宣告版本

    $ sudo apt-get install golang-1.8-go

    在 mac 上安裝:

    $ brew install go
  3. 使用 gcc、MinGW(windows)等編譯器編譯原始 Go 檔案

對於一般初學者來說,可以使用官網或是套件管理工具來安裝,可以留意環境變數是否有設定成功。

若有成功安裝,可以打開終端機執行 go version 會出現相關版本訊息,以下是 mac 的範例:

$ go version
go version go1.9 darwin/amd64

在 Go 中也提供了許多方便指令,方便我們編譯、測試和執行程式:

Go Web 程式設計入門教學

編譯檔案

$ go build

執行單元測試(unit testing),Go 一開始就內建了測試的機制,執行 go test 的話,會自動讀取套件目錄中的 *_test.go 來進行編譯、測試

$ go test

讓程式可以格式化 formatting,符合 go 的 convention

$ go fmt

安裝套件

$ go get

靜態分析潛在 bug

$ go vet

可以快速 build 並執行程式

$ go run

展示 go 相關文件

$ godoc

重新命名變數和函式

$ gorename

產生程式碼

$ go generate

你的第一個 Go 程式

在 Go 中程式運行的入口是套件 main。在這個程式中使用並導入了套件 "fmt",在 Go 程式中程式執行入口是 main function,若成功在終端機執行 $ go run,則會在終端機印出 Hello, World! 的 Go 程式,恭喜完成你的第一個 Go 程式了!

// 宣告程式屬於哪個 package
package main

// 引入套件
import (
"fmt"
)

// 程式執行入口
func main() {
// 使用 fmt 套件印出字串 word,使用 := 簡化原本變數宣告 var word string = "Hello, World!"
word := "Hello, World!"
fmt.Println(word)
}

另外一個範例是引入了 math/rand 套件產生隨機整數(由於環境中 seed 一樣所以會印出同樣值)

package main

import (
"fmt"
"math/rand"
)

func main() {
fmt.Println("My favorite number is", rand.Intn(10))
}

Go 有支援許多網路程式開發的套件,可以用很簡單的幾行就完成網路伺服器的建置:

package main

import (
"io"
"net/http"
)

// 處理 request 和 response 的函式
func hello(w http.ResponseWriter, r *http.Request) {
// 印出 hello world
io.WriteString(w, "Hello world!")
}

func main() {
// router 讓網址可以對應處理函式
http.HandleFunc("/", hello)
// 監聽 8000 port
http.ListenAndServe(":8000", nil)
}

總結

以上就是關於 Go 程式語言的基本教學介紹和環境建置,接下來的文章我們將透過 Golang Web 程式設計來學習 Go 這個程式語言的方方面面。

參考文件

  1. A tour of go
  2. Go Tutorial
  3. Go by Example
  4. Go Programming Language: An Introductory Tutorial
  5. Go tour Exercise
  6. Ubuntu Go install
  7. 從Go看現代程式語言

(image via cuelogic

Python Web Flask 實戰開發教學 - SQLAlchemy 與 ORM

· 閱讀時間約 8 分鐘

Python Web Flask 實戰開發教學

Web 開發涉及層面很廣,包含了前後端開發、資料庫優化、平行處理、負載平衡、高可用性、資訊安全、雲端伺服器部屬等議題,本系列文章將透過介紹 Python Web Flask 實戰開發來學習現代化網站開發的方方面面。上一篇我們完成了環境建置,這一單元我們將進入 MVC 架構的 Models 部分並學習如何使用 SQLAlchemy 建立和資料庫互動的 ORM 機制。

Python Web Flask 實戰開發教學

什麼是 MVC?

MVC 模式(Model–view–controller)是軟體工程中的一種軟體架構模式,把軟體系統分為三個基本部分:模型(Model)、視圖(View)和控制器(Controller)。

  • 控制器(Controller)- 對 Request/Response 進行處理並透過 Controller 把 Model 的資料串接到 View(Templates)。
  • 視圖(View) - 直接面對使用者的使用者介面設計。
  • 模型(Model) - 負責和資料庫互動,儲存資料。

使用 MVC 的好處在於可以用更高階的角度去思考整個程式架構提高程式可重用性和降低程式耦合性。 事實上 Django、Rails 和 ASP.NET MVC 等較成熟的 Web 框架也是參考 MVC 的架構去設計。

什麼是關聯式資料庫(RDB)?

Database 資料庫一個資料儲存的集合,方便我們去讀取新增刪除修改,而 Relational Database(關聯式資料庫)廣泛應用資料庫應用程式中,它把資料儲存在行列表格中,有可能不同資料表的內容會彼此依賴關聯。常見的關聯式資料庫,例如:MySQL、Postgres、Oracle、MSSSQL、SQLite,本文我們將使用 SQLite 這個輕量級的關聯式資料庫來當做範例教學。

什麼是 ORM?

ORM 指的是 Object Relational Mapping(物件關聯對應),是一種程式設計技術,用於實現物件導向程式語言裡不同類型系統的資料之間的轉換。一般而言物件導向是從軟體工程基本原則(例如:耦合、聚合、封裝)的基礎上發展起來的,然而關聯式資料庫則是從數學理論發展而來的,兩套理論存在顯著的區別。為了解決這個不符合的現象,物件關聯對映技術搬演著中介層的角色,讓開發可以使用物件方式來操作資料庫,而不用使用 SQL 語法,當然若是要使用複雜的操作,仍需要使用到 SQL 語法。

更多 SQL 語法學習:SQL語法教學- 1Keydata

Python Web Flask 實戰開發教學

Flask SQLAlchemy 使用設定

SQLAlchemy 是 Python 社群最廣泛使用的 ORM 套件。為了方便使用 ORM 來操作資料庫,我們使用 SQLAlchemy 的封裝 Flask SQLAlchemy 來進行 Models 的建立(當然你也可以單獨使用 SQLAlchemy)。以下是 SQLAlchemy 使用的簡單範例:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
# 設定資料庫位置,並建立 app
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)
# 建立資料表欄位
from main import db

class Todo(db.Model):
# __table__name = 'user_table',若不寫則看 class name
# 設定 primary_key
id = db.Column(db.Integer, primary_key=True)
content = db.Column(db.String(80))

def __init__(self, content):
self.content = content

def __repr__(self):
return '<Todo %r>' % self.content
from flask_script import Manager, Server
from main import app
from models import Todo

# 設定你的 app
manager = Manager(app)
# 設定 python manage.py runserver 為啟動 server 指令
manager.add_command('runserver', Server())

# 設定 python manage.py shell 為啟動互動式指令 shell 的指令
@manager.shell
def make_shell_context():
return dict(app=app, Todo=Todo)

if __name__ == '__main__':
manager.run()

操作指令:

$ python manage.py shell
>>> db.create_all()

CRUD 操作設計

CRUD 是一般網路應用程式最常見的資料庫操作(create, read, update, delete),接著我們要使用 session 來操作我們的 CRUD 功能,首先先在終端機中輸入 $ python manage.py shell 後進行資料庫指令模擬操作(要注意的是 Flask SQLAlchemy 針對每個 request 會創建一個新的 session,若沒有 commit 的操作即被丟棄):

  1. 新增(Create) 新增一筆資料後將它加到 db.session 中,完成 commit:

    >>> todo = Todo(content='hacking')
    >>> db.session.add(todo)
    >>> db.session.commit()

2. 讀取(Read)
Model.query 是 db.session.query(Model) 的簡寫,所以我們可以使用以下方式讀取資料庫資料:

取得所有 todo 資料

todos = Todo.query.all() todos

限制 1 筆資料

todos = Todo.query.limit(1).all()

正向/逆向排序

todos = Todo.query.order_by(Todo.content).all() todos = Todo.query.order_by(Todo.content.desc()).all()

取得第一筆資料

todo = Todo.query.first()

取得 primary key=1 一筆資料

todo = Todo.query.get(1)


- 分頁(Pagination)

todos = Todo.query.paginate(1, 10)

總頁數

todos.pages

上/下一頁

todos.prev() todos.next()


- 條件查詢(Filter)

todo = Todo.query.filter_by(content='hacking').first()

todos = Todo.query.filter(Todo.id > 1).all()


3. 修改(Update)

```python
todo = Todo.query.filter_by(contant='hacking').update({
'content': 'reading'
})
db.session.commit()
  1. 刪除(Delete)

    >>> todo = Todo.query.filter_by(content='reading').first()
    >>> db.session.delete(todo)
    >>> db.session.commit()

資料庫關聯用法

在關聯式資料庫中,最重要的就是資料表之間的關聯,透過關聯的使用,可以讓我們取得我們想要的資料。舉例而言,一篇部落格文章通常會對應多則評論,所以若是建立好關係則可以透過文章去取得所有和這篇文章有關的評論。同理,一篇文章通常會有多個 tag,而一個 tag 通常對應多篇文章,所以是個多對多關係。

  • 一對多
# 建立資料表欄位
from main import db

class Todo(db.Model):
# __table__name = 'user_table',若不寫則看 class name
# 設定 primary_key
id = db.Column(db.Integer, primary_key=True)
content = db.Column(db.String(80))
user_id = db.Column(db.String(80), db.ForeignKey('user.id))

def __init__(self, content):
self.content = content

def __repr__(self):
return '<Todo %r>' % self.content

class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80))
todos = db.relationship(
'Todo',
backref='user', # ref 可以讓我們使用 Todo.user 進行對 User 操作
lazy='dynamic' # 有使用才載入,提昇效能
)

def __init__(self, name):
self.name = name

def __repr__(self):
return '<User %r>' % self.name

操作方式:

>>> user = User.query.get(1)
>>> new_todo = Todo('Booking')
>>> new_todo.user_id = user.id
>>> db.session.add(new_todo)
>>> db.session.commit()
>>> user.todos
  • 多對多
tags = db.Table('todo_tags',
db.Column('todo_id', db.Integer, db.ForeignKey('todo.id')),
db.Column('tag_id', db.Integer, db.ForeignKey('tag.id'))
)

# 建立資料表欄位
from main import db

class Post(db.Model):
# __table__name = 'user_table',若不寫則看小寫 class name
# 設定 primary_key
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(80))
content = db.Column(db.String(80))

def __init__(self, title, content):
self.title = title
self.content = content

def __repr__(self):
return '<Todo %r>' % self.content

class Tag(db.Model):
# __table__name = 'user_table',若不寫則看 class name
# 設定 primary_key
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(80))

def __init__(self, title):
self.title = title

def __repr__(self):
return '<Tag %r>' % self.title

操作方式:

# 創建 3 個 todo
>>> todo_1 = Todo('Python')
>>> todo_2 = Todo('JS')
>>> todo_3 = Todo('R')

>>> tag_1 = Tag('coding')
>>> tag_1.tags = [todo_1, todo_2]
>>> db.session.add()
>>> db.session.commit()

Python Web Flask 實戰開發教學

Flask Migration(Alembic)使用

隨著網路應用程式的發展,我們的 models 會不斷變更,為了記錄所有有關 models 的改動,我們使用 Flask-Migrate 這個 extensions。所有 models 改動都會記錄在 migration 檔案中,就像是資料庫的 git 一樣方便版本控制。

安裝 Flask-Migrate

$ pip install Flask-Migrate

將 db 加入 Flask-Migrate 控制:

from flask_migrate import Migrate, MigrateCommand
from flask_script import Manager, Server
from main import app
from models import Todo

# 設定你的 app
manager = Manager(app)
# 設定 python manage.py db 來管理 models
manager.add_command('db', MigrateCommand)
# 設定 python manage.py runserver 為啟動 server 指令
manager.add_command('runserver', Server())

# 設定 python manage.py shell 為啟動互動式指令 shell 的指令
@manager.shell
def make_shell_context():
return dict(app=app, Todo=Todo)

if __name__ == '__main__':
manager.run()

使用 Flask-Migrate 操作 DB:

# 初始化
$ python manage.py db init
# 記錄 model 變化
$ python manage.py db migrate
# 更新同步到 db
$ python manage.py db upgrade
# 查詢指令
$ python manage.py db --help

總結

本文介紹了資料庫、關聯式資料庫、ORM 的概念,我們也實際使用了 Flask SQLAlchemy 和 Flask-Migrate 來操作我們的資料庫。在接下來章節中我們將持續介紹 Python Web Flask 實戰開發,並學習現代化網站開發的方方面面。

延伸閱讀

  1. Wiki MVC
  2. Python Web 程式設計入門實戰線上課程

(image via basicsofwebdevelopment

Python Web Flask 實戰開發教學 - 簡介與環境建置

· 閱讀時間約 10 分鐘

Python Web Flask 實戰開發教學 - 簡介與環境建置

Web 開發涉及層面很廣,包含了前後端開發、資料庫優化、平行處理、負載平衡、高可用性、資訊安全、雲端伺服器部屬等議題,本系列文章將透過介紹 Python Web Flask 實戰開發來學習現代化網站開發的方方面面。一開始先從簡介和環境建置開始吧!

什麼是 Python?

Python 是一種物件導向、直譯式的跨平台電腦程式語言,它包含了一組功能完備的標準庫和豐富套件生態系,可以輕鬆完成很多常見的任務(例如:讀寫檔案、自然語言處理、網路爬蟲、網站開發、機器學習等),因為它可以很輕易整合其他底層語言(例如:C/C++ 等),所以又稱為膠水語言。它的語法簡單,與其它大多數程式設計語言使用大括弧不一樣,它使用空白縮進來定義語句塊。由於具備簡潔易學等特性,許多開發者推薦 Python 為初學者第一個學習的程式語言。由於版本更迭,我們接下來討論的主要是以 Python3 為主,若電腦沒有安裝的話,你可以在官方網站下載,若你不是安裝 Anaconda 這個 all-in-one 版本的話(自帶許多套件和科學運算工具,也可以建立虛擬開發環境),記得要安裝 pipIPython

接下來我們將以 Anaconda 這個開發環境為主要講解環境。由於我們假定讀者已經有一些 Python 基礎,所以我們會跳過有關 Python 語法的基本較邵,若您對於 Python 入門基礎較不熟悉的話建議參考 Python 101 快速入門教學 ,此外我們也提供了 Python Web 程式設計入門實戰線上課程 可以參考。那就讓我們開始吧!

什麼是 Flask?

Python Web Flask 實戰開發教學 - 簡介與環境建置

Flask 是一個使用 Python 撰寫的輕量級 Web 應用程式框架,由於其輕量特性,也稱為 micro-framework(微框架)。Flask 核心十分簡單,主要是由 Werkzeug WSGI 工具箱Jinja2 模板引擎所組成,Flask 和 Django 不同的地方在於 Flask 給予開發者非常大的彈性(當然你也可以說是需要思考更多事情),可以選用不同的用的 extension 來增加其功能。相比之下,Django 雖然完善但技術選擇相對不彈性,不論是 ORM、表單驗證或是模版引擎都有自己的作法。事實上沒有最好的框架,只有合適的使用情境,Django 相比之下適合需要快速的開發大型的應用程式,和 Ruby 中的 Ruby on Rails 相似,而 Flask 則是相對輕量彈性,更像是 Ruby 界的 Sinatra。若讀者想先體驗看看 Flask 的程式狀況,以下是 Flask 簡易運行的程式,啟動測試伺服器後,可以在瀏覽器中(http://localhost:5000/)印出 Hello World!

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
return "Hello World!"

if __name__ == "__main__":
app.run()

Python Web 開發環境建置

所謂工欲善其事,必先利其器,要開發好的應用程式必須先準備好開發環境才行。以下介紹我們在接下來開發 Python Flask Web 應用程式所需要安裝的開發環境工具(以下以 Mac OS 等 Unix-like 作業系統為示範,若是 Windows 使用者建議安裝 Virtualbox 並運行 Linux Ubuntu 作業系統,參考安裝文件):

  1. Microsoft VSCode 編輯器 Microsoft VSCode 是 Microsoft 推出的編輯器(非整合開發環境 IDE),夾帶著 Microsoft 過去打造 Visual studio 整合開發環境的豐富經驗,相比 Sublime Text 和其他編輯器,VSCode 的優勢在於開源且活躍的開發社群、內建 debugger 框架、原生 Git 整合、套件整合容易等特性。所以對於初學者來說 VSCode 是一個蠻適合入門的開發環境。它的安裝方式也十分簡易,在官網下載後按照指示安裝完成即可。

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    我們可以安裝 Python 語法和格式檢查的相關 Python 套件幫助除錯:

    Python Web Flask 實戰開發教學 - 簡介與環境建置

  2. 終端機環境(iTterm/內建 terminal) terminal(終端機)是我們下指令的地方,許多時候我們進行程式開發時不會使用 GUI 的介面而是使用下指令方式請電腦做相對應的行為。在 Linux 和 Mac 裡面都有內建的 terminal 的應用程式,若你是 Mac 用戶想使用更便利的工具(分割視窗、熱鍵、搜尋、自動補完等)可以額外安裝 iterm2 做使用。

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    下指令($ 為提示字元,不用輸入):

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    對於有志於從事程式開發相關工作的讀者建議可以多熟悉指令碼的輸入,更多指令碼可以參考鳥哥撰寫的 Linux 基本指令介紹Linux 學習資源

  3. Git 版本控制系統/註冊 GitHub 帳戶 Git 是一種分散式版本控制系統,可以讓我們可以更方便地管理我們的程式碼。在網路上有非常多優秀的 Git 教學文件(連猴子都能懂的Git入門指南寫給大家的 Git 教學初心者 Git 上手攻略)。安裝 Git 方式是到官網下載軟體,依照指示安裝。

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    互動式語法學習:

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    在介紹完 git 之後我們來了解一下 GitHub。GitHub 是一個可以存放 git 程式碼專案的平台,透過 GitHub 我們可以接觸到最新的開放原始碼資訊,也可以將我們的程式碼開源出來。

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    從 GitHub 上複製程式碼

    Python Web Flask 實戰開發教學 - 簡介與環境建置

    # 複製一份到本地端
    $ git clone https://github.com/happycoderorg/flask101.git
    # 移動到資料夾
    $ cd flask101

    常見 Git 指令:

    # 初始化專案
    $ git init
    # 查看狀態
    $ git status
    # 檢查差異
    $ git diff
    # 將變更檔案放入暫存區
    $ git add index.py
    # 使用 commit -m 提交變更
    $ git -a -m 'init commit'
    # 查看歷史
    $ git log
    # 放棄已經 commit 的檔案重回暫存區
    $ git reset HEAD index.py
    # 放棄檔案變更
    $ git checkout index.py
  4. Anaconda Python3 版本 Anaconda 是一個 all-in-one 的 Python 開發環境,對於初學者來說是個十分合適的開發環境包。Anaconda 具備了幾項特點:

    • 便於安裝許多流行的科學、數學、工程、數據分析的 Python 模組
    • 開源和免費
    • 跨平台支持:Linux、Windows、Mac
    • 支持 Python 版本切換,方便建立不同的虛擬開發環境
    • 內建 Spyder 編輯器和 Jupyter Notebook 環境

    安裝流程也十分簡單,進入 Anaconda 首頁,選擇對應作業系統(這邊使用 Mac OS): Python Web Flask 實戰開發教學 - 簡介與環境建置

    選擇對應 Python 版本下載,我們使用 Graphical Installer(圖像介面安裝方式),接著在下載完成時按照預設的安裝方式完成安裝; Python Web Flask 實戰開發教學 - 簡介與環境建置

    若是完整安裝成功,可以打開終端機輸入,若是顯示 Python 3.6.0 :: Anaconda 4.3.0 (x86_64) 版本號即安裝成功:

    $ python -V
    Python 3.6.0 :: Anaconda 4.3.0 (x86_64)

    接著要建立我們專案虛擬環境,這樣在安裝操作套件時比較不容易被污染到 root 的環境,啟動後會出現(套件名稱)的提示字元:

    # 顯示目前虛擬環境列表
    $ conda info -e
    # 創建虛擬環境
    $ conda create -n 套件名稱 python=3.6
    # 進入虛擬環境(若是 Windows cmder 環境不用加 source) ,成功後提示字元變成:(套件名稱)$
    $ source activate 套件名稱
    # 離開虛擬環境(若是 Windows cmder 環境不用加 source)
    $ source deactivate

建立第一個 Flask 開發專案

使用 pip 管理 Python 模組

# 安裝模組
$ pip install 模組名
# 移除模組
$ pip uninstall 模組名
# 搜尋模組
$ pip search 模組名

通常開發專案時我們會將已安裝模組名稱和版本號存成一個列表,以便下次安裝使用:

$ pip freeze > requirements.txt

根據 requirements.txt 列表安裝模組:

$ pip install -r requirements.txt

建立虛擬環境

在了解 pip 套件管理工具後我們正式來建立一個 Flask 的專案:

建立專案資料夾

$ mkdir python-flask-todo-app
$ cd python-flask-todo-app

建立獨立虛擬環境

$ conda create -n python-flask-todo-app python=3.6
$ source activate python-flask-todo-app

安裝 Flask 模組

$ pip install flask

設定 Config 設定檔案

建立設定檔 config.py 檔案在專案資料夾的根目錄中:

class Config(object):
pass

class ProdConfig(Config):
pass

class DevConfig(Config):
DEBUG = True

建立一個 main.py 檔案初始化 Flask App 和使用其 API,若是一切正常在終端機執行 python main.py 會在瀏覽器網址列輸入 localhost:5000 後看到 Hello World 了!

from flask import Flask
from config import DevConfig

# 初始化 Flask 類別成為 instance
app = Flask(__name__)
app.config.from_object(DevConfig)

# 路由和處理函式配對
@app.route('/')
def index():
return 'Hello World!'

# 判斷自己執行非被當做引入的模組,因為 __name__ 這變數若被當做模組引入使用就不會是 __main__
if __name__ == '__main__':
app.run()

使用 Flask Script

Flask Script 是 Flask 常用的 extensions,可以讓我們使用指令列來操作 Flask 程式並在 shell 環境下操作 app context,使用方式如下:

安裝模組

$ pip install flask-script

建立 manage.py 於根目錄

from flask_script import Manager, Server
from main import app

# 設定你的 app
manager = Manager(app)
# 設定 python manage.py runserver 為啟動 server 指令
manager.add_command('runserver', Server())

# 設定 python manage.py shell 為啟動互動式指令 shell 的指令
@manager.shell
def make_shell_context():
return dict(app=app)

if __name__ == '__main__':
manager.run()

當執行 $ python manage.py runserver 即會執行測試伺服器,$ python manage.py shell 可以在對話指令列中中輸入 app 找到被引入的 <Flask 'main'>,可以讓我們在互動式指令對話框中測試操作使用。

總結

本文介紹了如何建置 Python Web 開發環境,我們也實際完成了我們第一個 Python Flask 程式。在接下來章節中我們將持續介紹 Python Web Flask 實戰開發,並學習現代化網站開發的方方面面。

延伸閱讀

  1. Wiki Flask (web framework)
  2. Python Web 程式設計入門實戰線上課程

(image via fedoramagazine

自學程式設計學習資源懶人包

· 閱讀時間約 7 分鐘

隨著資訊科技的發展,目前網路上和坊間有許多的自學電腦科學和程式設計的學習資源,但初學者在面對琳琅滿目的學習資源往往無所適從,因此本文整理了散落各地的自學程式設計學習資源懶人包和學習藍圖提供讀者參考,也歡迎讀者一起補充:)

學習程式設計最重要的是了解電腦科學背後的思考模式和邏輯分析,對於非本科系或是程式設計自學者來說,培養興趣累積成就感是最重要的,建議先從解決生活上著手,透過寫程式解決生活上的問題,等累積了興趣和成就感後重新學習基礎電腦科學知識。以下是初學者學習藍圖建議供讀者參考:

  1. 確認你的學習動機、設定個學習目標
  2. 選擇一門適合你的程式語言入門和工具
  3. 大量閱讀、參與課程、動手實作解決生活上問題,把手弄髒並記錄心得
  4. 組織、參與社群、練習問個好問題
  5. 熟悉函數程式設計、物件導向、框架、設計模式
  6. 重新學習資料結構、演算法、作業系統/系統程式、計算機組織、網路通訊等基礎電腦科學知識(程式解題)
  7. 學習進階電腦科學知識

延伸閱讀:

  1. 非本科生,我想半路出家學寫程式,該如何開始?
  2. Python Web 程式設計入門實戰
  3. JavaScript 程式設計新手村課程
  4. HappyCoder 自學程式設計學院臉書社團

實務程式設計

  1. [中 & 英] Codecademy

    codecademy

    Codecademy 是非常知名的線上學習程式設計的平台(有許多免費的課程),課程設計互動性和趣味性都相當不錯,相當適合初學者練習。課程也運用遊戲化(gamification)徽章和關卡設計也讓學習者更有動力學習。目前除了 HTML/CSS/JavaScript 網頁程式設計外,也有 Python、Ruby、Java 等程式語言可以學習(課程也有持續更新),不過 Codecademy 的內容相對基本,若想要在熟悉語法外更進一步學習實務開發應用程式的話就要額外再找其他學習資源了,但仍不失為一個很好的新手入門方式。

    課程深度:✦ 費用:免費、付費

  2. [英] Code School

    codeschool

    Code School 也是蠻知名的線上程式設計學習平台,與 Codecademy 類似,除了有提供學員線上即時動手實作練習、遊戲化徽章累積的設計外也有影片教學。課程內容也相當豐富貼近實務(JavaScript、Ruby、Git 等)。

    課程深度:✦✦ 費用:免費、付費

  3. [英] Code.org

    code.org

    適合中小學或完全初學的朋友練習,使用圖形化 Scratch 式拖拉程式設計方式。透過簡單的方式體驗程式設計的背後邏輯運作原理。

    課程深度:✦ 費用:免費

  4. [英] W3Schools Online Web Tutorials

    w3schools

    提供豐富的 Web 開發相關學習資源和查詢,適合在實際開發時學習參考查詢使用。

    課程深度:✦ 費用:免費

  5. [中 & 英] Mozilla Developer Network

    MDN

    由 Mozilla 社群維護的技術文件和教學內容,提供 Open Web 相關學習資源(HTML/CSS/JavaScript、Web API、Python)和 API 標準查詢。

    課程深度:✦✦ 費用:免費

  6. [英] FreeCodeCamp

    freecodecamp

    主要提供 HTML/CSS/JavaScript 線上學習資源和討論社群,並提供非營利組織專案實習機會。

    課程深度:✦ 費用:免費

  7. [英] TreeHouse

    teamtreehouse

    TreeHouse 和 Code School 類似,有影片教學也有互動練習,主要提供各種主流程式語言和技術組合的線上課程,包含了行動應用開發、網站開發、遊戲開發等實務課程。

    課程深度:✦✦ 費用:付費

  8. [中 & 英] Udemy

    udemy

    Udemy 是一個全面性的線上課程平台,提供素人講師線上分享技能的機會,課程十分多元貼近實務。除了網站開發、行動應用程式等技術領域外,也有許多非技術領域的課程(例如:行銷管理、創業、攝影、音樂創作等)。

    課程深度:✦✦ 費用:付費

  9. [中 & 英] Udacity

    udacity

    Udacity 與許多知名企業(Google、Facebook)合作提供許多前沿技術的線上教學,例如:人工智慧、深度學習、VR、Web、Mobile 技術等。此外,也提供微專業(Nanodegree)一系列課程和工作機會的媒合。

    課程深度:✦✦✦ 費用:免費、付費

  10. [英] DataCamp

    datacamp

    可以稱作資料科學版本的 Codecademy,使用互動學習方式線上學習資料科學,對於資料科學有興趣的讀者可別錯過了。

    課程深度:✦✦ 費用:免費、付費

基礎電腦科學

  1. [英] Coursera

    coursera

    Coursera 與許多知名大學合作(Stanford、賓州大學、北京大學、台灣大學等),提供教授可以線上授課的平台,學生也可以在家就上到一流學府的課程。與一般課程一樣需要繳交作業,若能完成課程修業規定,可以申請證書。

    課程深度:✦✦✦ 費用:免費、付費

  2. [英] edX

    edx

    edX 與 Coursera 類似與許多知名大學合作(MIT、哈佛大學、UCB等),提供教授可以線上授課的平台。

    課程深度:✦✦✦ 費用:免費、付費

程式解題

  1. [英] LeetCode

    leetcode

    LeetCode 又稱軟體工程師的 GRE(英文檢定),是一個線上解題平台,內含許多演算法和資料結構的題目,是許多準備軟體工程面試的面試者常用的工具。

  2. [英] Hacker Rank

    hackerrank

    Hacker Rank 也是一個線上解題平台,除了解題外也提供教學內容幫助學員學習,適合不想單純解題的使用者。

  3. [英] CodeFights

    codefights

    CodeFights 可以讓你和世界各地的程式設計師對戰,讓寫程式變成像圍棋一樣一場場對奕,十分有趣。

  4. [英] Codewars

    codewars

    Codewars 也是一個程式挑戰的解題平台,提供許多種語言讓使用者可以練習。

  5. [英] Kaggle

    kaggle

    Kaggle 和許多知名企業和單位合作提供資料科學問題,讓參賽者可以解題獲得獎勵和合作機會。

總結

以上整理了散落各地的自學程式設計學習資源懶人包和學習藍圖提供讀者參考,歡迎讀者一起補充,也歡迎加入我們的 臉書學習社群,分享你的自學程式設計心得和經驗。至於初學者若對於程式設計有興趣的話,不妨從 PythonJavaScript 入手,開啟你的程式設計之旅吧:)

參考文件

  1. Google - Guide for Technical Development
  2. Coursera
  3. edX
  4. Udacity
  5. OSS
  6. FreeCodeCamp
  7. Future Learn
  8. Stanford University
  9. MIT Open Courseware
  10. Obtaining a Thorough CS Background Online
  11. JavaScript 程式設計新手村課程
  12. 非本科生,我想半路出家學寫程式,該如何開始?
  13. 卡卡MOOC資源站

Python 101 快速入門教學

· 閱讀時間約 14 分鐘

Python 101 快速入門教學

Python Web 程式設計入門實戰課程準備上課囉!

Python 是一種物件導向、直譯式的跨平台電腦程式語言,它包含了一組功能完備的標準庫和豐富套件生態系,可以輕鬆完成很多常見的任務(例如:讀寫檔案、自然語言處理、網路爬蟲、網站開發、機器學習等),因為它可以很輕易整合其他底層語言,所以又稱為膠水語言。它的語法簡單,與其它大多數程式設計語言使用大括弧不一樣,它使用縮進來定義語句塊。由於具備簡潔易學等特性,許多開發者推薦 Python 為初學者第一個學習的程式語言。由於版本更迭,我們接下來討論的主要是以 Python3 為主,若電腦沒有安裝的話,你可以在官方網站下載,若你不是安裝 Anaconda 這個 all-in-one 版本的話(自帶許多套件和科學運算工具),記得要安裝 pipIPython

Python 設計風格

Python 主要設計的原則和特色就在於簡潔:應該會有一種明顯的作法(最好也只有一種),可以完成工作。

更多有關 Python 設計風格可以在終端機進入 python3 互動模式後輸入 import this

$ python3
Python 3.5.2 (default, Oct 11 2016, 05:00:16)
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import this

The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!

空白格式

首先,我們要了解 Python 和其他語言最大的不同就是使用縮排來切分程式碼,這和其他語言使用 不同。

for i in [1, 2, 3]:
print(i)
for j in [1, 2, 3, 4]:
print(j + i)

print('finish')

不過初學者很容易在縮排遇到問題,若是出現以下訊息就可以檢視是否哪裡縮排有問題:

IndentationError: expected an indented block

模組

在 Python 生態系中有豐富的模組和工具。一般情況預設不會載入任何模組,但當你有特定開發需求可以使用第三方工具將模組匯入(import)。若是當模組名稱很長時通常我們會使用別名。

import re as regex

my_regex = regex.compile('[0-9]+', regex.I)

若是只是需要模組中的特定功能,也可以使用比較精準的引入方式 from import,引入到整個命名空間中,使用時前面就不用寫模組名(但要注意有可能覆寫):

from collections import defaultdict, Counter
lookup = defaultdict(int)
my_counter = Counter()

資料型別

在 Python 有以下幾種內建的資料型別,基本資料型別有 Number、String、Boolean

  1. 數字(Number)

    num1 = 3
    num2 = 2
    num3 = num1 / num2
  2. 字串(String) 字串使用上會使用單引號或雙引號成對包起(', ")

    str = 'data engineer'
    # 字串長度
    len(str)
    # 原始字元
    es_str = r'\t'
    # 2
    len(es_str)

    若是多行的情形:

    multi_line_str = """
    多行
    多行
    """
  3. 布林值(Boolean) 決定邏輯判斷,TrueFalse。注意在 Python 中布林值首字是大寫

    is_num_bigger_than_one = 1 < 2

    在 Python 中 None 地位類似於 null

    x = None
    print(x == None)

    以下為 Python 的 Falsy 值:

  • False

  • None

  • []

  • ""

  • set()

  • 0

  • 0.0

    可以搭配 and, or, not 使用

  1. 列表(List) 列表可以說是 Python 中最基礎的一種資料結構。所謂列表指的就是一群按照順序排序的元素(類似於其他程式語言的 array,但多一些額外功能)。

    list_num = [1, 2, 3]
    list = ['string', 1, [], list_num]
    list_length = len(list_num)
    num_sum = sum(list_num)

    print(list_length)
    print(num_sum)

    運用 [] 取值(index 從 0 開始):

    x = range(10) # [0, 1, 2, ..., 9]
    zero = x[0] # 0
    nine = x[-1] # 9
    x[0] = -1

    切割([起始 index, 結束 index 但不包含]):

    print(x[:3]) # [-1, 1, 2]
    print(x[3:]) # [3, 4, 5,..., 9]
    print(x[1:5]) # [1, 2, 3, 4]
    print(x[0:-1]) # [1, 2, ..., 8]
    print(x[-1:-1]) # [-1, 1, ..., 9]

    檢查元素是否在列表中(逐一檢查,效率較差):

    1 in [1, 2, 3] # True

    串接列表:

    x = [1, 2, 3]
    x.extend([4, 5, 6])
    x = [1, 2, 3]
    y = x + [4, 5, 6]
    x = [1, 2, 3]
    x.append(0) # [1, 2, 3, 0]

    賦值方式:

    x, y = [1, 2]
    _, y = [1, 2]
  2. 元組(Tuple) Tuple 類似於 List 的兄弟,比較大差別在於 Tuple 是 immutable,也就是說宣告後不能修改。列表使用 [],而元組使用 ()

    my_list = [1, 2]
    my_tuple = (1, 2)
    my_list[1] = 3

    try:
    my_tuple[1] = 4
    except TypeError:
    print('cannot modify a tuple')

    多重賦值

    x, y = 1, 2
    x, y = y, x # x == 2, y == 1
  3. 字典(Dictionary)

    字典類似 map,包含鍵值與對應的值,可以快速取出對應值:

    dict1 = {} # 建議寫法
    dirct2 = dict()
    grades = { 'Mark': 70, 'Jack': 40 }

    grades['Mark']

    給定值:

    grades['happycoderorg'] = 100
    len(grades) # 3

    使用事先檢驗鍵或是使用 get 方法:

    try:
    grade = grades['XD']
    except KeyError:
    print('no grade for XD')

    grades.get('XD', 40) # 若無則使用 default 值

    取出所有值:

    grades = { 'Mark': 70, 'Jack': 40 }
    grades.keys() # 所有鍵值組成的 list
    grades.values() # 所有值組成的 list
    grades.items() # 所有鍵值組成的 tuple of list [('Mark', 70)]

    defaultdict

    當你檢查一個不存在的鍵值時,會用零參數函式添加一個事先設定的新值,這是一種比較優雅的作法

    在介紹 defaultdict 之前先介紹一般作法

    # 例外處理
    word_counts = {}
    for word in document:
    try:
    word_counts[word] += 1
    except KeyError:
    word_counts[word] = 1
    # 使用 get
    word_counts = {}
    for word in document:
    previous = word_counts.get(word, 0)
    word_counts[word] = previous_count + 1

    defaultdict 作法(不用每次檢查鍵直視否存在)

    # 匯入 defaultdict
    from collections import defaultdict

    word_counts = defaultdict(int) # 會生成 0
    for word in document:
    word_counts[word] += 1

    也可以使用 list 或 dict 甚至是自己定義的函式來做為 defaultdict 的零參數函式:

    dd_list = defaultdict(list)
    dd_list[1].append(2) # { 1: [2] }

    dd_list = defaultdict(list)
    dd_list['Mark']['City'] = 'Bay Area' # { 'Mark': { 'City': 'Bay Area'} }

    dd_list = defaultdict(lambda: [0, 0])
    dd_pair[2][1] = 1

    Counter:可以把一系列值轉成類似 defaultdict(int) 的東西,裡面每個值都對應到相應的數量,主要會使用來建立直方圖

    from collections import Counter

    c = Counter([0, 1, 2, 0]) # { 0: 2, 1: 1, 2: 1 }
    word_counts = Counter(document)

    每個 Counter 實例都有個 most_common 的方法

    for word, count in word_counts.most_common(10):
    print(word, count)
  4. 集合(Set) 集合類似數學中的集合,裡面包含不重複的元素值

    s = set()
    s.add(1) # { 1 }
    s.add(2) # { 1, 2 }
    s.add(2) # { 1, 2 }
    len(s) # 2
    1 in s # True

    集合在判斷元素是否存在的效率相對較好,此外,對於判斷不重複值也很方便

    list_item = [1, 2, 3, 1, 2, 3]
    set_item = set(list_item) # {1, 2, 3}
    lsit(set_item) # [1, 2, 3]

解析式列表(comprehensive list)

在 Python 我們通常會需要把某個 list 轉換成另外一個 list,比如只挑選其中幾個元素,或是對期中某些元素進行轉換。

even_numbers = [x for x in range(5) if x % 2 == 0]
squares = [x for x in range(5) if x % 2 == 0]
even_squares = [x * x for x even_numbers]

# 不操作值的話
zeros = [0 for _ in even_numbers] # 和 even_numbers 長度一樣值都為 0 的串列

建立 set 和 dict

square_dict = { x : x * x for x in range(5) }
square_set = { x * x for x in [1, -1] } # { 1 }

pairs = [(x, y) for x in range(10) for y in range(10)] # (0, 0), (0, 1)
p = [(x, y) for x in range(3) for y in range( x + 1, 10)]

函式

函式(function)是重複使用的程式區塊,有輸入輸出。在 Python 中我們會使用 def 來定義函式:

def sum(x, y):
return x + y

Python 的函數和 JavaScript 一樣,屬於一級函式(first-class)。我們可以將函數指定給某個變數,然後把它傳給某個函數中,就像是平常把參數傳入函式一樣。

def apply_f(fun):
return fun(3, 2)

def sum(x, y):
return x + y

sum_fun = sum
num = apply_f(sum)
print(num) // 5

匿名函數使用方式(類似 ES6 arrow function 簡化寫法,前面是參數後面是操作):

y = apply_f(lambda x: x + 4)

函式參數預設值:

def my_print(message="default"):
print(message)

my_print("hello python")
my_print()

args 與 kwargs

若我們希望函式可以接受任意參數,我們可以使用 args(由無名稱參數組成的元組) 和 kwargs(由無名稱參數組成的字典):

def magic(*args, **kwargs):
print('unnamed args:', args)
print('keywords args:', kwargs)
magic(1, 2, key='word', key2='word2')

# unnamed args: (1, 2)
# keywords args: {'key': 'word', 'key2': 'word2'}

可以用來協助建立以函式當做參數的高階函式:

def double(f):
def g(*args, **kwargs):
return 2 * f(*args, **kwargs)
return g

def f2(x, y):
return x + y

g = doubler_correct(f2)
print(g(1, 2))

常見內建函式

除了自己可以建立函式外,Python 本身也提供許多好用的內建函式:

  • all:列表中所有元素為真

    all([True, 1, { 3 }]) # True
    all([True, 1, { }]) # False
    all([]) # True,沒有元素為假
  • any:列表中只要有任何元素為真

    any([True, 1, {}]) # True
    any([]) # False,沒有元素為真
  • enumerate:列舉

    我們常需要反覆取得列表中每個元素及其索引值

    # choice 1
    for i in range(len(documents)):
    document = documents[i]
    do_something(i, document)

    # choice 2
    i = 0
    for document in documents:
    do_something(i, document)
    i += 1

    使用 enumerate:

    for i, document in enumerate(documents):
    do_something(i, document)

    # 僅需要 index
    for i, _ in enumerate(documents): do_something(i)
  • zip:合併將多個 list 合併成 tuple of list

    list1 = ['a', 'b', 'c']
    list2 = [1, 2, 3]
    zip(list1, list2) # [('a', 1), ('b', 2)]

    zip(*[('a', 1), ('b', 2), ('c', 3)]) == zip(('a', 1), ('b', 2), ('c', 3)) # [('a', 'b', 'c'), ('1', '2', '3')]
    # * 可以參數拆分
    def add(a, b): return a + b
    add(1, 3) # 4
    add([1, 3]) # TypeError
    add(*[1, 3]) # 4
  • range:取得一序列

    range(0, 10) # 0, 1, 2, ... 9
  • random:生成隨機數字

    import random

    randoms = [random.random() for _ in range(4)] # 生成長度為 4 內涵值為 0 - 1 不含 0 的 list

    事實上,random 產生的是偽隨機數字,透過 seed 設定可以取得同樣值

    import random
    random.seed(10) # 把 seed 設為 10
    print(random.random()) # 0.5714025946899135
    random.seed(10) # 把 seed 設為 10
    print(random.random()) # 0.5714025946899135

    隨機產生範圍內數字:

    random.randrange(10)
    random.randrange(3, 6)

    針對列表隨機排列:

    num = range(10)
    random.shuffle(num)
    random.choice(['Mark', 'Bob', 'Jack'])

    隨機取樣不放回:

    nums = range(10)
    random.sample(nums, 3)

    隨機取樣放回:

    nums = range(10)
    random.choice(nums, 3)
  • sort:針對 list 進行排序(由小到大),會改變原來的 list。sorted 不會改變原來 list

    x = [4, 1, 2, 3]
    y = sorted(x) # [1, 2, 3, 4] 不會改變到 x
    x.sort() # x 變成 [1, 2, 3, 4]

    若想改成由大到小排序

    x = sorted([-4, 1, -2, 3, key=abs, reverse=True]) # [-4, 3, -3, 2] 絕對值由大到小

    若是在 key 指定一個函數,就會用這個函數結果去做排序

    wc = sorted(word_counts.items(), key=lambda (word, count): count, reverse=True) # 針對單字數量多到小排序
  • partial:使用函式工具創建另一個函式

    from functools import partial
    def exp(base, power):
    return base ** power
    two_to_the = partial(exp, 2)
    print_two_the(3)
  • map:

    def multiply(x, y):
    return x * y
    map(multiply, [1, 2], [1, 2]) # [1, 4]
  • filter:

    def is_even(x):
    return x % 2 == 0
    filter(is_even, [2, 5, 6]) # [2, 6]
  • reduce:

    def multiply(x, y):
    return x * y
    reduce(multiply, [1, 2, 3]) # 1 * 2 * 3

控制流程

  1. if...elif...else

    if 1 > 2:
    message = 'if onlt 1 were greater than two'
    elif 1 > 3:
    message = 'elif == else if'
    else:
    message = 'else'

    三元運算子:

    parity = 'even' if x % 2 == 0 else 'odd'
  2. for...in

    較複雜情況我們會搭配 continue 和 break 使用:

    for x in range(10): # 0...9 不含 10
    if x == 3:
    continue
    if x == 5:
    break
    print(x)
  3. while

    x = 0
    while x < 10:
    print('x is less than 10')
    x += 1

生成器(generator)與迭代操作

事實上,list 有個問題就是很容易變得很大。例如:range(1000000) 就會製造出一個包含一百萬的元素的 list。若是想要使用其中幾個元素,效能就會變得很差。此時使用生成器(generator)就是一個每次只生成所需數值的一種 lazy 作法。

使用函式和 yield

def lazy_range(n):
i = 0
while i < n:
yield i
i += i
for i in lazy_range(10):
do_something(i)

或是在小括號使用運算解析式

lazy_evens_below_20 = (i for i in lazy_range(20) if i % 2 == 0)

另外,每個 dict 都有一個叫做 items() 的方法

iteritems() # 可以一次生成一個鍵值對

裝飾器(decorator)

裝飾器本身是一個函式,主要是借助閉包力量產生一個可以修飾函式的函式:

@print_fun(title='title:')
def add(*tup):
return sum(tup)

# 以下兩者相同
add(1, 2, 3, 4)
add = print_fun(title='title:')(add)

# 裝飾器撰寫
def print_fun(title):
def decorator(func):
def modified_func(*args, **kwargs):
result = func(*args, ** kwargs)
print(title, result)
return modified_func
return decorator

正規表達式

與許多程式語言一樣,Python 同樣提供正規表達式的用法,可以方便擷取文字。

import re

print.all([
re.match('a', 'cat'),
re.search('a', 'cat')])

物件導向程式設計(OOP)

Python 也是物件導向程式語言:

class Set:
def __init__(self, values=None):
# 建構函數
s1 = Set()
s2 = Set([1, 2, 3])
self.dict = {}
if values is not None:
for value in values:
self.add(value)
def __repr__(self):
return "Set" + str(self.dict.keys())
def add(self, value):
self.dict[value] = True
def contains(self, value):
return value in self.dict
def remove(self, value):
del self.dict[value]
# 使用物件
s = Set([1, 2, 3])

s.add(4)

print(s.contains(4))

例外狀況

若是程式出現錯誤的話會送出 exception,若不妥善處理的話程式很有可能會掛掉,在 Python 中例外處理可以使用 try...except:

try:
print(1/0)
except ZeroDivisionError:
print('cannot divide by zero')

總結

本文快速介紹了 Python 的基礎概念,當讀者學會了 Python 後,事實上可以嘗試使用 Python 開發不同的網路應用程式或是資料科學,甚至是自然語言處理的應用。更多 Python 教學內容都在 Python Web 程式設計!

延伸閱讀

  1. 15 Essential Python Interview Questions
  2. 8 Essential Python Interview Questions*
  3. Python Interview Questions
  4. What are good Python interview questions?
  5. Top 40 Python Interview Questions & Answers
  6. Top Python Interview Questions And Answers
  7. Python Interview Questions
  8. 12步教你理解Python装饰器

(image via fedoramagazine

JavaScript 101 快速入門教學

· 閱讀時間約 13 分鐘

JavaScript 101 快速入門教學

JavaScript 程式設計新手村課程準備上課囉!

Java 和 JavaScript 雖然名稱相似,但卻是熱狗和狗的差別。JavaScript 是由 Netscape 工程師 Brendan Eich 於 1995 年僅花 10 天所設計的程式語言,也因為一些歷史因素,JavaScript 成為被誤解最深的程式語言。JavaScript 是一種直譯式、基於原型(prototype based)的物件導向程式語言,但又具有函數式程式設計(Functional programming)的特性。其具備簡單好上手、應用範圍廣泛,容易有成就感,但精通不易等特性。過去一段時間 JavaScript 一直被認為是玩具語言,難登大雅之堂。但隨著版本的演進,再加上 NodeJS 的出現,讓 JavaScript 由黑翻紅成為程式語言的當紅巨星,目前雄據在程式語言排行榜前幾名,除了網頁開發外,在許多的領域都可以看到 JavaScript 的身影。本文將快速帶領大家掌握 JavaScript 重要且核心的觀念。

環境建置

JavaScript 的檔案只要使用一般的文字編輯器即可編輯(存成 .js 檔案),也可以使用 Sublime Text 等編輯器進行開發,JSBin 這個線上工具進行測試(當然你也可以使用 Chrome、Firefox 等瀏覽器的開發者工具)。除了編輯器外,實際開發上我們也會需要用到 Node.js 開發環境 和 NPM 套件管理系統(按照 Node.js 官方指示即可安裝)。Node.js 是一個開放原始碼、跨平台的、可用於伺服器端和網路應用的執行環境。

JavaScript 程式使用方式(HTML 中引入)

  1. 內嵌於 <head></head> (因 JS 為直譯式程式語言,讀到即會執行)

    <head> 
    <script>
    alert(Hello JavaScript);
    </script>
    </head>
  2. 內嵌於 <body></body> 之中 (可以讓 HTML 優先載入)

     <body> 
    <script>
    alert(Hello JavaScript);
    </script>
    </body>
  3. 外部引入檔案置於 <head><body> 內 (推薦使用)

     <script src="js/main.js"></script>

注意外部引入的 <script></script> 中不可再寫 JS。

變數

在程式語言中變數是一個暫時儲存資料的地方,賦值給變數的值都會有對應的資料型態,然而 JavaScript 是弱型別(Weak type)所以會有自動轉型的情形。

在 JavaScript 中,全域變數將使用 var,而在 ES6 中為了解決變數污染或誤用情形將 block-scope 的變數使用 let,若你需要固定不變的常數則是使用 const。 其中變數型別又分為:Primitive Data Type:String、Number、Boolean( true 或 false)、undefinded、null,Reference Data Types:Object 兩種,差別在於將物件變數賦值給另外一個變數時是把引用賦值給新變數,所以當新變數更改屬性時會影響到原來物件。

Primitive Data Type:

var num = 12;
const str = 'Mark';

function checkLike() {
let isActived = true;
}

// console.log 可以讓開發者透過瀏覽器開發者工具看到訊息,方便除錯
console.log(num);
console.log(str);
// 因為 let 是 function block scope,故會產生 "ReferenceError: isActived is not defined 錯誤
console.log(isActived);

Reference Data Types:

// 將物件變數賦值給另外一個變數時是把引用賦值給新變數,所以當新變數更改屬性時會影響到原來物件
let a = { name: 'Zuck' };
console.log(a);
let b = a;
b.name = 'Jack';
console.log(a);

運算子/運算元

在程式語言中都需要運算子,在 JavaScript 中有賦值運算子、算數運算子、比較運算子、邏輯運算子等不同運算子。

  1. 賦值運算子:使用 = 給定值給變數

    // Mark
    const name = 'Mark';
  2. 算數運算子:四則運算

    // 4
    const sum = 1 + 3;
  3. 比較運算子:數值比較

    const age = 23;
    // true
    const canVote = age >= 20;
    // false
    const canVote = age < 20;
  4. 邏輯運算子:邏輯判斷

    const a = true;
    const b = true;
    // 且,要兩個都 true
    const result1 = a && b;
    // 或,只要有一個 true,即為 true
    const result2 = a || b;

流程控制(flow control)

在 JavaScript 中和許多程式語言一樣有 if...elseswitch 條件判斷以及在處理陣列上很常使用的迴圈(當有明確次數時使用 for,當沒有明確數字時使用 while

另外要注意的是在 JavaScript 中的 falsey 值:undefinednullNaN0""(空字串)和 false,以上幾種情況在邏輯判斷時會轉換成 false

  1. if...else

    // 可以投票
    if(age > 20) {
    console.log('可以投票!');
    }
  2. switch:當條件很多時可以善用 switch 判斷,記得要在每個 case 後寫 break,不然會全部都執行

    const country = 'Taiwan';
    switch(grade) {
    case 'Taiwan':
    console.log('hello' + country);
    break;
    case 'Japan':
    console.log('hello' + country);
    break;
    case 'Korea':
    console.log('hello' + country);
    break;
    default:
    console.log('hello' + country);
    }
  3. for:當你知道程式需要重複執行幾次時可以使用 for 迴圈

    const arr = ['Mark', 'Zuck', 'Jack'];
    for(let i = 0; i < arr.length; arrr++) {
    console.log(arr[i]);
    }
  4. while:當你程式不知道需要重複執行幾次時可以使用 while 迴圈

    // 從 1 累加到 10
    const num = 1;
    while(num <= 10) {
    let sum += num; // sum = sum + num
    num += 1;
    }
  5. do...while:當迴圈次數不明確時,可以使用 while,而 do while 會至少執行一次

    let x = 0;
    while(x < 10) {
    console.log(x);
    x++;
    }

    let y = 0;
    do {
    console.log(y);
    y++;
    } while(i < 10);

函式/函數(function)

函數是一種可以讓一段程式區塊重複使用的程式撰寫方式,在 JavaScript 中函數屬於一級物件(first class object),可以將函數當參數或變數傳遞,其扮演非常重要的角色,也讓 JavaScript 在函數式程式設計(functional programming)上更容易發揮。 函數可以傳入參數(如下的 x, y),也有可能沒有。函數使用 return 回傳值,若沒寫則回傳 undefined

function sum(x, y) {
return x + y;
}

sum(12, 20);

在 ES6 簡化了函數的使用出現了箭頭函數(arrow function):

const sum = (x, y) => {
return x + y;
};

sum(1, 2);

物件(object)

物件是一種儲存資料的資料結構,可以對應成真實世界的物件(有屬性值和方法),一般而言主要有三種建立方式:

  1. 使用 new Object

    var obj = new Object();
  2. 使用 {}

    var obj = {
    name: 'Mark',
    age: 23
    }
  3. 使用建構函數

    雖然 JavaScript 並非是 class-based 的物件導向程式語言,而是 prototype-based 的物件導向程式語言,但在 JavaScript 可以透過 function 建立類別的宣告函數(在 ES6 中已有 class 可以使用,但只是個語法糖):

    // 實務上建構函數命名採單字首字大寫。狗狗物件有 name, age 屬性,方法是 wow 
    function Dog(name, age) {
    // 屬性值
    this.name = name;
    this.age = age;
    // 每個實例都會有一份方法副本
    this.wow = function() {
    console.log('wow!wow');
    }
    }
    // 多個實例共用,可以減少記憶體等資源運用
    Dog.prototype.cry = function() {
    console.log('QQQ');
    }
    const dog = new Dog('lucky', 2);
    // wow!wow!
    dog.wow();

DOM & BOM

事實上 HTML 可以轉換成一棵物件樹,也稱為 Document Object Model(DOM)。在撰寫網頁應用程式時往往需要操作到瀏覽器元素,我們通常是透過選取我們想要改變的元素(選擇器),然後修改我們的物件屬性

  1. 物件模型

    所謂的物件模型(Object Model)對於HTML 網頁來說,是一種規範如何存取HTML 元素、CSS 樣式和 JavaScript 程式碼的一種機制,可以將HTML元素、CSS樣式和 JavaScript 程式碼視為物件

  2. BOM

    js101

    BOM 就是 Browser Object Model 中文叫做瀏覽器物件模型,window 物件是瀏覽器最頂層物件,其下有 document(DOM)、history、location、navigator、screen 子物件。window 物件不須經過宣告,可直接使用,代表目前瀏覽器視窗。事實上,所有的全域變數、函式、物件,其實都是屬於 window 物件,而 BOM 物件的使用可讓我們操作包含開啟/關閉視窗,改變視窗大小,計時器與取得網址、存取瀏覽器屬性等

  3. DOM

    文件物件模型(Document Object Model,DOM)是給 HTML 與 XML 文件使用的一組 API。簡單的說就是將文件(文件可以想成單一網頁)物件化,以便提供一套通用存取的方式來處理文件內容。DOM 提供 HTML 網頁一種存取的方式,可以將 HTML 元素轉換成一棵節點樹,每一個標籤和文字內容是為一個節點,讓我們可以走訪節點 (Nodes) 來存取 HTML 元素

    <!doctype html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>My title</title>
    </head>
    <body>
    <h1>My header</h1>
    <a href="">My link</a>
    </body>
    </html>

    js101

    要操作 DOM 元素前要選取要操作哪個

    • 根據ID名稱選取 document.getElementById(elementId)

    • 根據元素名稱選取 document.getElementsByTagName(tagName)

    • 根據名稱選取 document.getElementsByName(name)

    • 根據 Class 名稱選取 document.getElementsByClassName(classname)

    有很多元素符合,回傳的是 NodeList 物件集合,使用 item() 存取 (注意 Element's'),迭代使用 forEach 不然就要轉陣列

    document 物件有提供使用 CSS 選擇器來選取元素,效能較好

    • document.querySelectorAll() 方法 document 物件的 querySelectorAll() 方法可以取得 HTML 的節點陣列或清單,為一個 NodeList 物件(若要使用 map 方法需要轉陣列,不然只能用 forEach )

    • document.querySelector() 方法 只會回傳一個符合的元素,沒有就回傳 null

    範例:

    <div class="info"></div>
    <div class="info"></div>

    <div id="danger"></div>

    <script type="text/javascript">
    document.querySelector('#danger').innerHTML = '<h1>嘿嘿,是我</h1>';

    document.querySelectorAll('.info').forEach((value, index) => {
    value.innerHTML = '<h1>坐著打,普天之下排名第二</h1>';
    });
    </script>

事件處理(event handler)

事件處理(Event Handlers)是 JavaScript 非常重要的功能,事件是用來處理 JavaScript 與 HTML 之間的互動、建立動畫效果並和使用者互動

  • 事件處理簡單說就是當一個事件發生時(網頁載入、按下右鍵等),程式會相對應做出怎樣的處理

  • 例如:當使用者按下按鈕時會觸發 click 的事件(事件發生)並讓按鈕變成紅色(處理事件),這就是一種事件處理機制

事件處理機制

事件處理 = 事件種類 + 事件處理方法
  • 事件種類(Event Type) 又稱事件名稱 (Event Name),為一個字串,說明發生了什麼事件,例如:click (點擊)、mousemove (滑鼠滑過)

  • 事件處理(Event Handlers) 係指處理事件的函數名稱,當事件發生時要呼叫哪個函數進行處理

// 當發生 click 事件,會發出 alert 
btn.addEventListener('click', function() {
alert('被點了!');
});

完整範例:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<button id="btn">點我點我</button>
<script type="text/javascript">
const btn = document.querySelector('#btn');

btn.addEventListener('click', function() {
alert('被點了!');
});
</script>
</body>
</html>

非同步處理(Ajax)

傳統上我們會使用 <form> 表單和後端程式作互動,然而每次提交表單送出請求給伺服器,伺服器接收並處理傳來的表單,然後送回一個新的網頁。使用 Ajax 應用可以僅向伺服器發送並取回必須的數據,並在客戶端採用JavaScript 處理來自伺服器的回應,不僅減少伺服器負擔也加快反應速度

同步 vs. 非同步

JavaScript 101 快速入門教學

依序執行,等到上一個函數任務執行完才能執行下一個

JavaScript 101 快速入門教學

不會因為上一個函數尚未執行完(例如:回傳結果)就卡住,會往下執行下一個任務

什麼是同步/非同步?

  • 非同步係指程式不會因為上一個函數尚未執行完(例如:回傳結果)就卡住,會往下執行下一個任務

  • 同步就是要等到上一個函數任務執行完才能執行下一個,是依序執行

由於 DOM 事件處理Ajax 呼叫是非同步處理,所以大部分人會為 JavaScript 貼上非同步程式設計的標籤

什麼是 Ajax?

  • Ajax 全名:Asynchronous Javascript And XML,指的是一套綜合了多項技術的瀏覽器端網頁開發技術

  • 雖然 Ajax 中使用 XML 為名,不過 Ajax 不是指一種單一的技術。現在許多應用都使用更輕量的 JSON 進行資料傳輸

  • 可以完成不刷頁局部更新應用,使用者體驗較好。不過要小心回調地獄(callback hell)

簡易 Ajax 實作

// 若需要支援跨瀏覽器,還需要額外檢驗
if (typeof XMLHttpRequest != 'undefined') {
// 一般使用 XMLHttpRequest 物件
const xhr = new XMLHttpRequest();
const REQUEST_URL = 'http://163.29.157.32:8080/dataset/6a3e862a-e1cb-4e44-b989-d35609559463/resource/f4a75ba9-7721-4363-884d-c3820b0b917c/download/393625397fc043188a3f8237c1da1c6f.json';

// 監聽是否完成
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
console.log(xhr.responseText);
}
}

xhr.open('GET', REQUEST_URL);
xhr.send();
}

JSON 基礎概念

  • JSON(JavaScript Object Notation)是一種由Douglas Crockford 構想設計、輕量級的資料交換語言,以文字為基礎,且易於讓人閱讀

  • JSON 雖然起於 JavaScript,但資料格式與語言無關,目前很多程式語言都支援 JSON 格式資料的生成和解析

  • JSON 的官方 MIME 類型是 application/json,其副檔名是 .json

  • 基本格式 { "key": "value" }{ "key": ["value1", "value2"] }


JSON 長這樣

{
"name": "John Smith",
"address":
{
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021"
},
"phoneNumber":
[
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "fax",
"number": "646 555-4567"
}
]
}

總結

以上介紹了新手上路 JavaScript 入門核心基礎概念,大家可以善用 JSBin 實際動手操作,並參考 MDNW3CSchool 的案例會更清楚整體觀念喔!更多豐富教學內容都在 JavaScript 程式設計新手村課程!

延伸閱讀

  1. 用十分鐘瞭解 陳鍾誠的程式設計課 (採用JavaScript + C的原因)
  2. You-Dont-Know-JS
  3. JavaScript與前端程式設計入門自學參考
  4. JavaScript Garden
  5. JavaScript核心
  6. [稀土掘金日报] JavaScript 开发者必备的资源合集
  7. 專為中學生寫的 JavaScript 程式書
  8. nzakas/computer-science-in-javascript
  9. 重新介紹 JavaScript

(image via mprmahmoudzalt