2019年9月30日 星期一

好站 : Python Learn

今天偶然逛到下面這個 PythonLearn 教學網站, 特點是提供了完整的教材, 包括簡報, Youtube 視訊教學影片, 還可直接下載 PDF 書籍, 影片, 聲音等等, 規劃得非常好. 雖然是英文解說, 或許會讓人卻步, 但影片均有英文字幕可輔助理解, 換個角度看, 學完全部課程英文也有進步豈不一舉兩得?

http://www.pythonlearn.com/index.php





這個視訊教學最棒的地方是, 左邊是簡報, 右邊是講解的老師, 他會一邊說明一邊用手寫筆在簡報上畫線寫字, 就跟實際在課堂上課那樣, 而且還更清楚. 網路上真的有蠻多寶貝, 這麼棒的教學何必花大錢趕去補習班學呢? 我要找零碎時間慢慢把他看一遍.

2019年9月29日 星期日

2019 年第 39 周記事 : 小貓收養記

昨晚在鄉下車庫操作洗衣機時, 好像聽到很微弱的貓咪叫聲, 但四處看了一下並無所獲. 今早起來卻聽到車庫傳來小貓的咪咪叫聲, 出去車庫一看, 竟然是一隻未開眼的小貓, 毛色是黃白色的, 肯定是寓居我家的那隻野貓生的, 據說母貓若聞到小貓身上有人味會不敢回來, 所以我就不管牠, 等母貓回來把牠叨走.




一直到傍晚我要回高雄前, 母貓都沒出現, 看來小貓變棄嬰了, 牠一整天在車庫到處爬, 一邊爬一邊叫, 肯定是肚子餓, 這樣下去可能會餓死. 我傳 Line 給菁菁, 她說她要養, 所以就把牠放進糖果紙盒帶回高雄, 菁菁好像把牠當人類嬰兒般照顧 :




本周除了繼續學習 Django 外, 就是看韓劇陽光先生, 已到 20 集, 快到尾聲了. 日俄即將一戰, 美國束手旁觀, 凱爾怕尤金感情用事便利用職權命令尤金返國, 高愛信知道後去跟尤金說她想隨他去美國, 其實是想在途經日本時跳船, 以便營救被武臣會綁架到日本的李正文大人. 雖然尤金說破了愛信的意圖, 他還是願意成全, 拿來偽造的結婚證書, 為愛信戴上戒指, 以夫妻身分前往日本. 來到東京後, 尤金找到了愛信父母當年拍攝結婚照的攝像館, 拍下了他們的結婚照 :





在港口送別尤金後, 愛信剛好被武臣會的浪人認出而追殺, 看到這一幕的尤金為了解救愛信沒有上船, 兩人逃到美國駐日公使館前用最後一顆子彈朝使館窗戶開槍, 頓時使館士兵立刻蜂擁而出, 他們阻擋得了武臣會浪人的追殺嗎?

我查維基並沒有武臣會, 指的應該是黑龍會才對, 這是以前日本浪人組成的秘密情報網, 首腦是日本慈善家頭山滿, 日本會走上軍國主義道路與黑龍會的泛亞洲思想脫不了干係, 甚至可說, 沒有黑龍會就沒有同盟會, 辛亥革命可能也不會成功, 因為他們認為清朝的存在阻礙了他們形塑大東亞新秩序的進程, 如果鼓動革命鬧個天翻地覆更容易亂中取勝. 黑龍會名稱來自黑龍江, 因為他們最早的目標就是要把俄國人的勢力趕回黑龍江以北.


2019-10-14 補記 :

這隻小貓在送到水某同事家找她們家剛生產的美國短毛貓當乳母, 剛開始狀況還不錯, 會找母貓的乳頭吸允, 但幾天後的早上發現一動也不動, 已經無生命現象了. 有可能他一出生就有缺陷, 所以母貓才棄養吧.

2019年9月28日 星期六

田寮一線天健行

上週老張約今天去田寮走一走, 原想應該沒甚麼事就答應了, 昨天才想到這個周末二哥要去走馬踏瀨參加迎新, 估計來回一小時車程, 必須 06:30 出發才能在 07:30 到老張家. 所幸是騎機車去比較快, 若是開車還要回家換機車肯定來不及.

我對田寮很陌生, 因為沒有親朋好友住在那裏. 這次是要去大崗山的一線天健行, 成員就大師夫婦, 老張, 我, 小琪, 還有大師的尊翁六人. 車停在朝元寺前, 從寺旁的小路往上走, 本想走到減肥洞, 無奈前陣子雨後雜草叢生, 就往回走到一線天, 然後攀了一小段階梯到觀景亭喝茶聊天.





回到山下發現還是只有我們兩台車, 這裡似乎不太有人來玩啊! 從山上觀景亭往下看, 田寮似乎都是丘陵地, 住戶並不多. 中午到大師家叨擾, 由持有中餐丙級的小琪下廚, 大師夫人又採購菜餚準備了豐盛的午餐. 由於對大師尊翁打的自家燕巢芭樂汁讚不絕口, 回家時又獲贈一瓶帶回, 呵呵, 真是一個快樂的周末.

市圖還書 15 本

今天清理了一批借書 :
  1. 微積分
  2. 網頁應用程式設計 :使用Node和Express (左新)
  3. 雙動能投資 :高報酬低風險策略
  4. 從法人手中賺到錢 :全台第一本類股籌碼分析全攻略 (陽明)
  5. 多空我都能賺 :必學7堂翻倍投資術
  6. 不好意思,我贏了 =Sorry,but I win! :掌握總經,點石成金投資法!
  7. 為你自己學Git (新興)
  8. It's django :用Python迅速打造Web應用!
  9. TensorFlow之外的好選擇
  10. 初入門紫微斗數
  11. 紫微斗數算你好工作 :科系、就業、職場通通選對!
  12. 八字氣數基礎講義
  13. 四柱推命奧秘傳(上) (中崙)
  14. 四柱推命奧秘傳(下)
  15. HTML5 & CSS3辭典 .第2版
希望能在年底前全部清完.

2019年9月26日 星期四

Python 學習筆記 : Django 2 測試 (二) : 模板基礎與靜態檔案

二月底做了初步的 Django 2.0 測試後, 準備下一步是建立包含 jQuery UI 的模板, 但卻發現以前學 jQuery UI 時趕時間沒有把筆記寫好寫滿, 就花了一段時間補寫, 接著四月又開始忙授課, 然後是陪二哥大學申請入學面試 .... 直到最近二哥上大學了, 我才又重新回到 Django 軌道 (還好婉拒了 12 月的授課).

經過了大半年, Django 版本也從 2.1.7 升到 2.2.5 所以先更新版本吧! 更新 Django 可在 pip install 後加上 -U 參數 :

pip3 install django -U

本篇測試參考了下面幾本書中的範例加以改寫 :
  1. It's django - 用 Python 迅速打造 Web 應用 (楊孟穎, 袁克倫, 碁峰)
  2. Python 新手使用 django 架站的 16 堂課 (何敏煌, 博碩)
  3. Python 新手使用 django 架站技術實作 (何敏煌, 林亮昀, 博碩)
  4. Python 網頁程式交易 App 實作 (林萍珍, 博碩)
  5. Beginning Django (Daniel Rubio, Apress)
  6. Django 2 Web Development Cookbook 3rd Edition(Jake Kronika, Packt)
  7. 一次搞定所有 Python Web 框架開發百科全書 (佳魁, 劉長龍) 
  8. 科班出身的MVC網頁開發 : 使用Python + Django (佳魁, 王友釗)
Django 2 官方教學文件參考 :

https://docs.djangoproject.com/en/2.2/

Python 學習筆記索引參考 :

Python 學習筆記索引

本系列之前的筆記參考 :

Python 學習筆記 : Django 2 測試 (一) : 請求與回應處理

線上教材參考 :

The Complete Guide To Install Django And Configure It
2019 iT 邦幫忙鐵人賽 : From Django 1.11 to Django 2.1 系列
Django 2 By Example 全书翻译、踩坑及教程

做完 Django 的請求與回應處理測試後, 本篇繼續測試 Django 2 的模版與靜態檔案功能. 由前一篇測試中可以發現, 即使可以用多行字串表示法 (三個連續引號對) 提高 views.py 中的 HTML 代碼可讀性, 但是在 views.py 的處理函數中直接用 HttpResponse 輸出網頁 HTML 字串的方式會使網頁內容與控制邏輯混在一起, 不符合 Django 鬆耦合 (llosely-coupled) 精神, 也不利於前後端之分工, 增加維護上的困難. 解決辦法就是利用 Django 的模板 (Template) 功能.

所謂的模板基本上就是一個嵌入變數與控制標籤的網頁檔, 利用 views.py 傳送變數值給模板引擎, 它會將變數以所傳送的值替換以便生成最終的 HTML 網頁, 此過程稱為渲染或繪製 (render), 如下圖所示 :




在建立網頁模板之前有一個準備工作要做, 就是建立存放模板檔案與靜態檔案的目錄, 這些都是整個網頁專案要用的, 所以要建在上層專案目錄底下.


一. 基本模板用法 : 

基本用法是指從視圖處理函數 views.py 中傳遞字典變數到模板網頁中. 首先須在專案中建立存放模板網頁與靜態檔案的目錄.

1. 新增 templates 與 static 目錄 :

在 Django 中, 所有副檔名為 htm 或 html 之網頁模板網頁模板會集中放在上層專案目錄下的一個專用子目錄中 (名稱可自訂, 例如 /templates). 另外, 網頁中可能會用到的圖檔, CSS 樣式檔, 以及 Javascript 程式等靜態檔案, 這些檔案也是集中放在上層專案目錄下的一個專用子目錄中 (名稱可自訂, 例如 /static, 這是設定檔 settings.py 中的預設值), 也可以在其底下建立三個子目錄以分類存放圖檔, 樣式檔, 以及 Javascript 程式檔. 這些目錄在新增專案時不會自動產生, 需手動建立 :

D:\Python\test\mysite>mkdir templates
D:\Python\test\mysite>mkdir static
D:\Python\test\mysite>cd static
D:\Python\test\mysite>mkdir images
D:\Python\test\mysite>mkdir css
D:\Python\test\mysite>mkdir js

這樣整個專案目錄結構如下 :


mysite (上層專案目錄)
     |____ manage.py
     |____ mysite  (下層專案目錄)
     |              |____ __init__.py
     |              |____ settings.py
     |              |____ urls.py
     |              |____ views.py  (自行添加)
     |              |____ wsgi.py
     |____ templates (網頁模板目錄)
     |____ static (靜態檔案目錄)
                    |____ images
                    |____ css
                    |____ js


這樣便可將模板網頁存放於 templates 子目錄下, 專案要用到的靜態檔案則分別置於 images, css, 與 js 下, 但在使用模版與靜態檔案之前還必須在專案設定檔 settings.py 中設定路徑, 這樣 Django 才能存取到這些手動建立的目錄下的檔案.


2. 編輯 settings.py 中的模版引擎與目錄設定 :

(1). 設定網頁模板路徑 :

開啟下層專案目錄下的 settings.py 檔, 其中的 TEMPLATES 變數的 DIRS 屬性就是用來設定模板路徑的, 需填入模版目錄的絕對路徑, 可用設定檔最前面建立的專案根目錄變數 BASE_DIR 與上面所建立的模板目錄名稱 'templates' 串接組合而成 :

os.path.join(BASE_DIR, 'templates')

此指令會將根目錄路徑與 templates 結合為模板目錄的絕對路徑 :

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],  
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

其中的 BACKEND 屬性用來設定所使用模版引擎, 預設為 DjangoTemplates, 也可以改用第三方引擎例如 jinja2, 這樣 BACKEND 就要改為 django.template.backends.jinja2.jinja2. 預設的模版引擎其實就很好用了.

經過上面的設定後便可以編輯網頁模板檔案了 (詳下).


(2). 設定靜態檔案路徑 :

開啟 settings.py 可發現在建立專案時, 此設定檔最底下已經預設靜態目錄 STATIC_URL 為 '/static', 在其底下再加入一個靜態目錄絕對位址變數  STATICFILES_DIRS :

STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static'),]

經過以上設定後, 就可以在網頁模板中使用靜態檔案了, 使用前須先宣告要用模板標籤載入靜態檔案, 語法如下 :

{% load static %}   

此 static 為內建之 django.contrib.staticfiles 模組所提供之指令, 在專案設定檔 settings.py 的 INSTALLED_APP 串列變數中已定義, 有些書上使用 {% load static from staticfiles %} 或 {% load staticfiles %} 都是較舊的用法, 現在應改用 {% load static %}, 參考 :

What is the difference between {% load staticfiles %} and {% load static %}

注意, load 指令只要使用一次即可, 通常放在網頁的 head 元素內. 載入宣告後才可以用模板標籤指令 static 載入靜態檔案, 語法如下 :

樣式檔 : <link rel="stylesheet" href="{% static "css/style.css" %}">
程式檔 : <script src="{% static "js/myscript.css" %}"></script>
圖片檔 : <img src="{% static "images/logo.jpg" %}">

注意, 模板標籤內的引號不影響外面屬性的引號, 不須單雙交替. 另外在 HTML 部分, link 元素使用 href 屬性連結樣式檔; 而 script 元素則用 src 屬性載入程式檔.


3. 編輯模版網頁與 views.py 處理函數 : 

經過以上設定就可以使用模板語法來編輯模板網頁了. 模板網頁中可以嵌入如下三種元素 : 變數, 標籤, 以及註解 :


 模板語法元素 說明
 {{ 變數 }} 來自 views.py 的變數用來直接替換該位置內容
 {% 標籤 %} 標籤用來控制資料顯示邏輯
 {# 註解 #} 註解會被模板引擎忽略


其中標籤語法操作的對象其實也是從 views.py 處理函數傳遞過來的變數, 這些變數是透過呼叫捷徑函數 django.shortcuts.render() 傳遞過來的, 在 views.py 中使用 render() 繪製網頁前須先匯入 :

from django.shortcuts import render

這樣便可直接呼叫 render() 函數了, 其參數有三 :

render(request, "template.htm", dict)

第一個參數 request 是包裝了客戶端請求訊息的 HttpRequest 物件; 第二個參數是要繪製的模板網頁檔案名稱 (放在 /templates 底下), 第三個參數是要傳遞給模板網頁的變數組成之字典, 例如 :

#views.py
from django.shortcuts import render
def helloworld(request):
    dict1={‘name’: ‘Tony’, ‘score’: 80}
    return render(request, ‘hello.htm’, dict1)

然後在模板網頁中直接用字典的鍵 (例如 {{ name }} 與 {{ score }}) 就可以存取所傳送的變數了, 如下圖所示 : 




如果要傳遞的變數很多, 自行組成字典較麻煩, 這時可以呼叫 locals() 函數, 它會傳回所有區域變數組成的字典, 例如 {‘name’: ‘Tony’, ‘score’: 80}, 可直接作為 render() 的第三參數, 但要注意, locals() 函數只會傳回所有區域變數組成的字典, 全域變數不包括在內. 例如 :

#views.py
from django.shortcuts import render
def helloworld(request):
    name=Tony

    score=80

    return render(request, ‘hello.htm’, locals())

此處兩個區域變數 name 與 score 都會被 locals() 組成字典傳遞給模板. 在模板網頁中同樣是直接用字典的鍵 (例如 {{ name }} 與 {{ score }}) 存取所傳送的變數.




注意, 因為 locals() 會將全部區域變數打包成字典, 因此如果區域變數本身就是字典, 物件, 串列或元組等容器類型變數, 則在模板網頁中, 必須使用物件的點運算子來存取存取元素變數. 模板引擎會以下列順序來查找所傳遞的變數 , 一找到便停止 :


 查找優先順序 相對於 Python 說明
 1. 字典鍵 {{ dict.key }} dict["key"] 字典鍵亦可用整數, 例如 {{ dict.0 }}
 2. 物件屬性 {{ obj.attr }} obj.attr attr 為物件 obj 之屬性
 3. 物件方法 {{ obj.method }} obj.method() method() 為物件 obj 之方法
 4. 串列或元組元素 {{ list.0 }} list.0 list 為串列


如果是字典變數, 則點運算子後面為 key (文字數字均可); 如果是物件變數, 點運算子後面是其屬性; 如果是串列或元組, 則點運算子後面是其索引. 下圖為字典變數的例子 :




注意, 這裡 locals() 傳遞的變數是 {'dict1': {'name': 'Tony', 'score': 80}}, 因此藥用 {{ dict1.name }} 存取 name 變數, 而非 {{ name }}.

前一篇的 Hello World 測試可以改用模板來做, 步驟如下 :

(1). 編輯模板網頁檔 :

此例需要兩個網頁檔 : hello.htm 與 home.htm (均存放於 /templates 底下), 前者顯示顯示 "Hello", 以及從 views.py 傳遞過來的人名與時間訊息, 底下有一個回首頁的連結圖檔. 關於 HTML5 網頁參考 :

網頁技術速學筆記 (一) : HTML 基礎

<--! hello.htm -->
<!DOCTYPE html>
<html>
<head>
  <title>Hello</title>
  <meta charset="utf-8">
  {% load staticfiles %}
  <link rel="stylesheet" href="{% static "css/hello.css" %}">
  <script src="{% static "js/hello.js" %}"></script>
</head>
<body>
  <p class="msg">Hello, {{ name }}, 現在的時間是 {{ now }}</p>
  <a href="/">
    <img src="{% static "images/home.jpg" %}" alt="回首頁">
  </a>
</body>
</html>

此網頁用到三種靜態檔案資源 : 樣式檔 (hello.css), 程式檔 (hello.js), 以及圖檔 (home.jpg), 須分別存放於 /static/css, /static/js, 與 /static/images 下.

另外編輯 home.htm 首頁檔 :

<--! home.htm -->
<!DOCTYPE html>
<html>
<head>
  <title>Hello</title>
  <meta charset="utf-8">
</head>
<body>
  <b>歡迎來到我的首頁!</b>
</body>
</html>

此兩檔案要放在 /templates 底下.


(2). 編輯樣式檔 hello.css :

/* hello.css  */
.msg {
  font-weight: bold;
  text-shadow: navy 3px 3px 3px;
  }

此檔案要放在 /static/css 底下.


(3). 編輯程式檔 hello.js :

其功能就是彈出一個訊息框而已 :

/* hello.js */
alert("Hello!");

此檔案要放在 /static/js 底下.


(4). 編輯 views.py 檔 :

#views.py
from django.shortcuts import render
from datetime import datetime

def hello(request, name):
    now=datetime.now()
    dict1={'name': name, 'now': now}
    return render(request, 'hello.htm', dict1)

def home(request):
    return render(request, 'home.htm', {})

視圖處理程式定義了兩個函數 hello() 與 home(). 其中 hello() 會傳遞名字與時間變數到模板網頁 hello.htm; 而 home() 則傳遞空字典到模板網頁 home.htm, 不需要傳變數第三參數就傳空字典.


(5). 編輯 urls.py 檔 : 

#urls.py
from django.contrib import admin
from django.urls import path
from mysite.views import home, hello

urlpatterns = [
    path('admin/', admin.site.urls),
    path('hello/<name>/', hello),
    path('', home),
]

此檔案處理 URL 路由, 第一個 path 是建立專案時預設的, 用來管理網站後台, 另兩個 path 則是將專案 URL 交由 views.py 中的函數處理, 所以開頭必須從 mysite.views 模組匯入 hello 與 home 這個函數. 也可以用 import mysite.views 匯入整個 views.py 模組, 但這樣 path() 的第二參數 (處理函數) 就要寫成 views.hello 與 views.home 了.

在上層專案目錄下啟動開發伺服器 :

python manage.py runserver 

然後於瀏覽器網址列輸入 http://127.0.0.1:8000/hello/Tony/ 結果如下 :




網頁載入後首先會執行 hello.js, 這會彈出一個顯示 'Hello' 的訊息窗, 按底下的 Home 圖檔會回到首頁.

D:\Python\test\mysite>python manage.py runserver     
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
September 26, 2019 - 16:37:36
Django version 2.2.5, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
[26/Sep/2019 16:37:41] "GET /hello/Tony/ HTTP/1.1" 200 367


二. 進階模板用法 :

進階用法是指使用模板標籤指令來控制網頁的顯示方式, 主要包含 if 判斷 (分支) 標籤與 for 迴圈標籤, 語法除了結尾多了 endif 與 endfor 外, 與 Python 是一樣的. 另外模板引擎還提供過濾器 (filter) 可對要輸出的變數進行格式化或特定運算.


1. if 判斷 (分支) 標籤 : 

利用變數運算式的真假值控制輸出何種網頁 :


 單一分支 雙重分支 多重分支
 {% if 條件式 %}
 輸出網頁
 (% endif %}
 {% if 條件式 %}
 輸出網頁1
 {% else %}
 輸出網頁2
 (% endif %}
 {% if 條件式 %}
 輸出網頁1
 {% elif %}
 輸出網頁2
 {% elif %}
 輸出網頁3
 {% else %}
 輸出網頁4
 (% endif %}


注意, endif 的 end 與 if 之間沒有空格, elif 的 el 與 if 之間也是, 若有空格會造成語法錯誤.


2. for 迴圈標籤 :

模板語言的迴圈包括 for 與 empty 標籤, 以及 forloop 物件所提供的 7 種屬性. for 標籤操作的變數是由 views.py 傳遞過來的可迭代變數, 例如串列或元組, 模板的迴圈與 Python 的 for~in 迴圈類似, 但需要 endfor 結尾, 而且不可使用 break 與 continue :


(1). for 迴圈語法 :

{% for 變數 in 可迭代變數 %}
網頁1
{% empty %}
網頁2 (迴圈為空時輸出)
{% endfor %}

注意, empty 標籤必須放在 for 迴圈的最後面 (即 endfor 標籤前面), 當迴圈為空 (即可迭代變數元素個數為 0) 時, 網頁1將不會輸出, 而是輸出夾在 empty 與 endfor 標籤中間的網頁2.

如果要做倒序迭代, 只要在可迭代變數後面加上 reversed 即可 :

{% for 變數 in 可迭代變數 reversed %}
網頁1
{% empty %}
網頁2 (迴圈為空時輸出)
{% endfor %}


(2). forloop 變數 :

為了方便控制迴圈與顯示內容, 模板引擎還提供了 forloop 物件變數, 它的 7 個屬性如下表所示 :


 迴圈變數 forloop 的屬性 說明
 forloop.counter 迴圈計數器 (1 起始)
 forloop.counter0 迴圈計數器 (0 起始)
 forloop.revcounter 倒數之迴圈計數器 (由總圈數遞減至 1)
 forloop.revcounter0 倒數之迴圈計數器 (由總圈數遞減至 0)
 forloop.first 是否為第一個迴圈 (True/False)
 forloop.last 是否為最後一個迴圈 (True/False)
 forloop.parentloop 上一層迴圈的 forloop 變數


(3). 過濾器 (filter) :

模板引擎提供了一些過濾器 (其實就是模板的內建函數), 以便在輸出變數前對變數內容或格式做修正或運算, 使最終能輸出符合需要之結果. 用法是在變數後面以管線符號 "|" 串接過濾器, 可串接多個過濾器, 模板引擎會依照順序處理 :

{{ 變數 | 過濾器1 | 過濾器2  | 過濾器3 | ... }} 

常用的過濾器如下表 :


 常用模板過濾器 說明 範例
 add 加上一個數值或做字串串接 {{ var | add:"2" }} 
 addslashes 跳脫特殊字元 (前面加上倒斜線 \) {{ var | addslashes }} 
 capfirst 將字串變數的首字元轉為大寫 {{ var | capfirst }}
 center  將字串變數冠上指定空格後置中 {{ var | center: "5" }}
 cut 從字串變數中刪除指定子字串 {{ var | cut: " " }} 刪除空白字元
 date 將 datetime 變數以指定格式顯示 {{ var | date: "D d M Y" }}
 default 當變數為空字串時輸出預設字串 {{ var | default: "預設值" }}
 dictsort 將串列變數中的字典依指定鍵遞增排序 {{ var | dictsort: "鍵" }}
 dictsortreversed 將串列變數中的字典依指定鍵遞減排序 {{ var | dictsortreversed: "鍵" }}
 divisibleby 測試數值變數是否可被指定數整除 {{ var | divisibleby: "7" }} 
 escape 跳脫字串變數內的 HTML 標籤 {{ var | escape }}
 filesizeformat 以 KB/MB 等單位顯示檔案大小 {{ var | fileformat }}
 first 取出串列變數中的第一個元素 {{ var | first }}
 join 將串列變數中的元素以指定字串串接 {{ var | join: "," }} 
 last 取出串列變數中的最後一個元素 {{ var | last }} 
 length 傳回串列變數的元素個數 (長度) {{ var | length }} 
 length_is 測試變數的長度是否為指定之長度 {{ var | length_is: "5" }} 
 linebreaks 將字串中的 \n 轉成 HTML 之 br 與 p {{ var | linebreaks }} 
 linebreaksbr 將字串中的 \n 轉成 HTML 之 br {{ var | linebreaksbr }} 
 linenumbers 將顯示之文字加上行號 {{ var | linenumbers }} 
 ljust 將字串變數冠上指定空格後置左 {{ var | ljust: "5" }}
 lower 將字串變數轉成小寫 {{ var | lower }}
 make_list 將字串拆成字元串列 {{ var | make_list }}
 random 隨機取出串列中的一個元素 {{ var | random }}
 rjust 將字串變數冠上指定空格後置右 {{ var | rjust: "5" }} 
 safe 以 HTML 格式讀取字串 (不須跳脫) {{ var | safe }} 
 slice 取出字串中的指定切片 {{ var | slice:":2" }} 
 slugify 將字串中的空白以 dash '-' 取代 {{ var | slugify }} 
 stringformat 以科學表示法顯示數字 {{ var | stringformat: "E" }} 
 striptags 移除字串中的 HTML 標籤 {{ var | striptags }} 
 title 將字串中每個字的第一字元大寫 {{ var | title }} 
 truncatechars 將字串中超出指定長度部分以 ... 取代 {{ var | truncatechars:"5" }} 
 upper 將字串轉成大寫 {{ var | upper }} 
 wordcount 傳回字串中的字數 {{ var | wordcount }} 
 yesno 依變數值為 True/False/None 轉成指定值 {{ var | yesno:"是, 否, 取消" }} 


有些過濾器有攜帶參數, 注意, 過濾器與參數之間用冒號緊密串接, 中間不可有空格, 否則會出現錯誤.

完整的過濾器用法參考 :

Built-in template tags and filters

以下為綜合分支與迴圈的測試範例, 使用 HTML 表格來彙整測試結果, 關於 HTML 表格用法參考 :

網頁技術速學筆記 (一) : HTML 基礎

模板網頁共有 6 個, 以首頁 home.htm 列舉到各項測試之超連結 :

<!-- 1. home.htm -->
<!DOCTYPE html>
<html>
<head>
  <title>Hello</title>
  <meta charset="utf-8">
</head>
<body>
  <h3>模板測試 2</h3>
  <ul>
    <li><a href="/if_test_1">分支測試 1 (if)</a></li>
    <li><a href="/if_test_2">分支測試 2 (if elif else)</a></li>
    <li><a href="/loop_test_1">迴圈測試 1 (有資料)</a></li>
    <li><a href="/loop_test_2">迴圈測試 2 (無資料)</a></li>
    <li><a href="/filter_test_1">過濾器測試 1</a></li>
    <li><a href="/filter_test_2">過濾器測試 2</a></li>
    <li><a href="/filter_test_3">過濾器測試 3</a></li>
  </ul>
</body>
</html>

第一個分支測試模板網頁 if_test_1.htm :

<!-- 1. if_test_1.htm -->
<!DOCTYPE html>
<html>
<head>
  <title>分支測試</title>
  <meta charset="utf-8">
  <style>
  table {background-color:blue;}
  td, th {background-color:white;}
  </style>
</head>
<body>
{% for stock in stocks %}
{{ stock }}
{% if not forloop.last %}
,
{% endif %}
{% endfor %}
</body>
</html>

第二個分支測試模板網頁 if_test_2.htm :

<!-- 2. if_test_2.htm -->
<!DOCTYPE html>
<html>
<head>
  <title>分支測試</title>
  <meta charset="utf-8">
  <style>
  table {background-color:blue;}
  td, th {background-color:white;}
  </style>
</head>
<body>
{% if hour > 18 %}
晚安
{% elif hour < 10 %}
早安
{% else %}
午安
{% endif %}
</body>
</html>

迴圈測試模板網頁 loop_test_1.htm :

<!-- 3. loop_test_1.htm -->
<!DOCTYPE html>
<html>
<head>
  <title>for 迴圈</title>
  <meta charset="utf-8">
  <style>
  table {background-color:blue;}
  td, th {background-color:white;}
  </style>
</head>
<body>
  <table border="0" cellspacing="1" cellpadding="5">
    <caption>股票列表</caption>
    <tr>
      <th>No.</th>
      <th>股號</th>
      <th>公司</th>
      <th>分類</th>
    </tr>
    {% for stock in stocks %}
    <tr>
      <td>{{ forloop.counter }}</td>
      <td>{{ stock.id }}</td>
      <td>{{ stock.name }}</td>
      <td>{{ stock.category }}</td>
    </tr>
    {% empty %}
    <tr>
      <td colspan=4>無股票資料</td>
    </tr>
    {% endfor %}
  </table>
</body>
</html>

第一個過濾器測試模板網頁 filter_test_1.htm :

<!-- 4. filter_test_1.htm -->
<!DOCTYPE html>
<html>
<head>
  <title>過濾器測試</title>
  <meta charset="utf-8">
  <style>
  table {background-color:blue;}
  td, th {background-color:white;}
  </style>
</head>
<body>
  <table border="0" cellspacing="1" cellpadding="3">
    <caption>過濾器測試 1</caption>
    <tr>
      <th>變數</th>
      <th>過濾器</th>
      <th>輸出</th>
    </tr>
    <tr>
      <td>i1=100</td>
      <td>i1|add:"200"</td>
      <td>{{ i1|add:"200"}}</td>
    </tr>
    <tr>
      <td>i2="100"</td>
      <td>i2|add:"200"</td>
      <td>{{ i2|add:"200"}}</td>
    </tr>
    <tr>
      <td>s1="A"</td>
      <td>s1|add:"200"</td>
      <td>{{ s1|add:"200" }}</td>
    </tr>
    <tr>
      <td>s2="I'm Tony."</td>
      <td>s2|addslashes</td>
      <td>{{ s2|addslashes }}</td>
    </tr>
    <tr>
      <td>s3="hello world"</td>
      <td>s3|capfirst</td>
      <td>{{ s3|capfirst }}</td>
    </tr>
    <tr>
      <td>s3="hello world"</td>
      <td>s3|truncatechars:"6"</td>
      <td>{{ s3|truncatechars:"6" }}</td>
    </tr>
    <tr>
      <td>s3="hello world"</td>
      <td>s3|wordcount</td>
      <td>{{ s3|wordcount }}</td>
    </tr>
    <tr>
      <td>s1="A"</td>
      <td>s1|center:"5"</td>
      <td>{{ s1|center:"5" }}</td>
    </tr>
    <tr>
      <td>s1="A"</td>
      <td>s1|ljust:"5"</td>
      <td>{{ s1|ljust:"5" }}</td>
    </tr>
    <tr>
      <td>s1="A"</td>
      <td>s1|rjust:"5"</td>
      <td>{{ s1|rjust:"5" }}</td>
    </tr>
    <tr>
      <td>s3="hello world"</td>
      <td>s3|cut:" "</td>
      <td>{{ s3|cut:" " }}</td>
    </tr>
    <tr>
      <td>now=datetime.now()</td>
      <td>now|date:"Y-m-d"</td>
      <td>{{ now|date:"Y-m-d" }}</td>
    </tr>
    <tr>
      <td>s4=""</td>
      <td>s4|default:"空字串"</td>
      <td>{{ s4|default:"空字串" }}</td>
    </tr>
    <tr>
      <td>d1=[{"id":"2330"},{"id":"2412"}]</td>
      <td>d1|dictsort:"id"</td>
      <td>{{ d1|dictsort:"id" }}</td>
    </tr>
    <tr>
      <td>d1=[{"id":"2330"},{"id":"2412"}]</td>
      <td>d1|dictsortreversed:"id"</td>
      <td>{{ d1|dictsortreversed:"id" }}</td>
    </tr>
  </table>
</body>
</html>

第二個過濾器測試模板網頁 filter_test_2.htm :

<!-- 5. filter_test_2.htm -->
<!DOCTYPE html>
<html>
<head>
  <title>過濾器測試</title>
  <meta charset="utf-8">
  <style>
  table {background-color:blue;}
  td, th {background-color:white;}
  </style>
</head>
<body>
  <table border="0" cellspacing="1" cellpadding="3">
    <caption><b>過濾器測試 2</b></caption>
    <tr>
      <th>變數</th>
      <th>過濾器</th>
      <th>輸出</th>
    </tr>
    <tr>
      <td>i1=14</td>
      <td>i1|divisibleby:"7"</td>
      <td>{{ i1|divisibleby:"7" }}</td>
    </tr>
    <tr>
      <td>i2=100</td>
      <td>i2|divisibleby:"7"</td>
      <td>{{ i2|divisibleby:"7" }}</td>
    </tr>
    <tr>
      <td>i3=1024</td>
      <td>i3|filesizeformat</td>
      <td>{{ i3|filesizeformat }}</td>
    </tr>
    <tr>
      <td>list1=['Python','Java','C++','Perl']</td>
      <td>list1|first</td>
      <td>{{ list1|first }}</td>
    </tr>
    <tr>
      <td>list1=['Python','Java','C++','Perl']</td>
      <td>list1|last</td>
      <td>{{ list1|last }}</td>
    </tr>
    <tr>
      <td>list1=['Python','Java','C++','Perl']</td>
      <td>list1|join:"/"</td>
      <td>{{ list1|join:"/" }}</td>
    </tr>
    <tr>
      <td>list1=['Python','Java','C++','Perl']</td>
      <td>list1|slice:":2"</td>
      <td>{{ list1|slice:":2" }}</td>
    </tr>
    <tr>
      <td>list1=['Python','Java','C++','Perl']</td>
      <td>list1|length</td>
      <td>{{ list1|length }}</td>
    </tr>
    <tr>
      <td>list1=['Python','Java','C++','Perl']</td>
      <td>list1|length_is:"4"</td>
      <td>{{ list1|length_is:"4" }}</td>
    </tr>
    <tr>
      <td>list1=['Python','Java','C++','Perl']</td>
      <td>list1|random</td>
      <td>{{ list1|random }}</td>
    </tr>
    <tr>
      <td>b1=True</td>
      <td>b1|yesno:"是, 否, 取消"</td>
      <td>{{ b1|yesno:"是, 否, 取消" }}</td>
    </tr>
    <tr>
      <td>b2=False</td>
      <td>b2|yesno:"是, 否, 取消"</td>
      <td>{{ b2|yesno:"是, 否, 取消" }}</td>
    </tr>
    <tr>
      <td>n1=None</td>
      <td>n1|yesno:"是, 否, 取消"</td>
      <td>{{ n1|yesno:"是, 否, 取消" }}</td>
    </tr>
  </table>
</body>
</html>

第三個過濾器測試模板網頁 filter_test_3.htm :

<!-- 6. filter_test_3.htm -->
<!DOCTYPE html>
<html>
<head>
  <title>過濾器測試</title>
  <meta charset="utf-8">
  <style>
  table {background-color:blue;}
  td, th {background-color:white;}
  </style>
</head>
<body>
  <table border="0" cellspacing="1" cellpadding="3">
    <caption><b>過濾器測試 3</b></caption>
    <tr>
      <th>變數</th>
      <th>過濾器</th>
      <th>輸出</th>
    </tr>
    <tr>
      <td>s1="Hello\nWorld"</td>
      <td>s1|linebreaks</td>
      <td>{{ s1|linebreaks }}</td>
    </tr>
    <tr>
      <td>s1="Hello\nWorld"</td>
      <td>s1|linebreaksbr</td>
      <td>{{ s1|linebreaksbr }}</td>
    </tr>
    <tr>
      <td>s1="Hello\nWorld"</td>
      <td>s1|linenumbers</td>
      <td>{{ s1|linenumbers }}</td>
    </tr>
    <tr>
      <td>s1="Hello\nWorld"</td>
      <td>s1|lower</td>
      <td>{{ s1|lower }}</td>
    </tr>
    <tr>
      <td>s1="Hello\nWorld"</td>
      <td>s1|upper</td>
      <td>{{ s1|upper }}</td>
    </tr>
    <tr>
      <td>s1="Hello\nWorld"</td>
      <td>s1|make_list</td>
      <td>{{ s1|make_list }}</td>
    </tr>
    <tr>
      <td>s2="<b>Hello</b>"</td>
      <td>s2|safe</td>
      <td>{{ s2|safe }}</td>
    </tr>
    <tr>
      <td>s2="<b>Hello</b>"</td>
      <td>s2</td>
      <td>{{ s2 }}</td>
    </tr> 
    <tr>
      <td>s3="hello world"</td>
      <td>s3|title</td>
      <td>{{ s3|title }}</td>
    </tr>
    <tr>
      <td>s3="hello world"</td>
      <td>s3|slugify</td>
      <td>{{ s3|slugify }}</td>
    </tr>
    <tr>
      <td>f1=0.00047108</td>
      <td>f1|stringformat:"e"</td>
      <td>{{ f1|stringformat:"e" }}</td>
    </tr>
    <tr>
      <td>s2="<b>Hello</b>"</td>
      <td>s2|striptags</td>
      <td>{{ s2|striptags }}</td>
    </tr>
  </table>
</body>
</html>

處理 URL 之路由檔 urls.py 內容如下 :

#urls.py
from django.contrib import admin
from django.urls import path
import mysite.views as views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('if_test_1/', views.if_test_1),
    path('if_test_2/', views.if_test_2),
    path('loop_test_1/', views.loop_test_1),
    path('loop_test_2/', views.loop_test_2),
    path('filter_test_1/', views.filter_test_1),
    path('filter_test_2/', views.filter_test_2),
    path('filter_test_3/', views.filter_test_3),
    path('', views.home),
]

視圖處理函數 views.py 內容如下 :

#views.py
from django.shortcuts import render
from datetime import datetime

def if_test_1(request):
    stocks={"台積電","中華電","統一超"}
    return render(request, 'if_test_1.htm', locals())

def if_test_2(request):
    now=datetime.now()
    hour=now.timetuple().tm_hour
    return render(request, 'if_test_2.htm', locals())

def loop_test_1(request):
    stock1={"id":"2330", "name":"台積電", "category":"半導體"}
    stock2={"id":"2412", "name":"中華電", "category":"通信網路"}
    stock3={"id":"2912", "name":"統一超", "category":"貿易百貨"}
    stocks=[stock1, stock2, stock3]
    return render(request, 'loop_test.htm', locals())

def loop_test_2(request):
    stocks=[]
    return render(request, 'loop_test.htm', locals())

def filter_test_1(request):
    i1=100
    i2="100"
    s1="A"
    s2=s2="I'm Tony."
    s3="hello world"
    s4=""
    d1=[{"id":"2330"},{"id":"2412"}]
    now=datetime.now()
    return render(request, 'filter_test_1.htm', locals())

def filter_test_2(request):
    i1=14
    i2=100
    s1="<b>Hello</b>"
    i3=1024
    list1=['Python','Java','C++','Perl']
    b1=True
    b2=False
    n1=None
    return render(request, 'filter_test_2.htm', locals())

def filter_test_3(request):
    s1="Hello\nWorld"
    s2="<b>Hello</b>"
    s3="hello world"
    f1=0.00047108
    return render(request, 'filter_test_3.htm', locals())

def home(request):
    return render(request, 'home.htm', {})

以 python manage.py runserver 指令啟動開發伺服器後, 在伺服器網址列輸入 localhost:8000 拜訪首頁如下 :




點首頁中的超連結即可測試各個功能. 在分支測試 1 中, 傳遞到模板的串列變數為 :

stocks={"台積電","中華電","統一超"}

在模板中使用了 for 迴圈來取出串列元素, 並使用 if 標籤來判斷是否要在元素後面加逗號, 在最後一個元素時 forloop.last 為真, 因此不會加逗號, 網頁輸出為 :

台積電 , 統一超 , 中華電

在分支測試 2 中, 傳送給模板的是目前的時數 hour (0~23) :

now=datetime.now()
hour=now.timetuple().tm_hour

在模板網頁中利用 if~elif~else 分支來判斷要輸出晚安, 早安, 還是午安.

在迴圈測試 1, 傳遞給模板網頁的是一個字典串列 stocks :

stock1={"id":"2330", "name":"台積電", "category":"半導體"}
stock2={"id":"2412", "name":"中華電", "category":"通信網路"}
stock3={"id":"2912", "name":"統一超", "category":"貿易百貨"}
stocks=[stock1, stock2, stock3]

在模板中用 for 迴圈與 forloop 變數於表格中顯示股票資訊. 而在迴圈測試 2 則是傳遞空串列變數 stocks 給相同的模板 loop_test.htm, 利用 empty 標籤來顯示無資料訊息, 結果如下 :




過濾器部分因太多, 所以分成三部分測試, 結果如下 :






關於過濾器摘要如下 :
  1. wordcount 是計算 "字" 數而非 "字元" 數, 亦即以空格為單位做區隔, 例如 "您好嗎?" 的 wordcount 是 1; 而 "您 好 嗎 ?" 的 wordcount 是 4. 
  2. 若直接輸出變數 {{ var }}, 模板引擎會自動將 HTML 標籤的角括號轉成 > 與 <, 但可以用 safe 過濾器阻止自動轉換. 
  3. linebreaksbr 會將字串變數中的跳行字元 "\n" 改為 "<br>", 例如 "Hello\nWorld" 會被轉成 "Hello<br>World". 而 linebreaks 則除了做此轉換外還會在外面套上 p 標籤, 例如 "Hello\nWorld" 會被轉成 "<p>Hello<br>World</p>".
  4. date 過濾器格式與 PHP 的極類似, 如果要製作 "2019-10-03 08:43:12" 這樣的輸出, 則其格式為 date:"Y-m-d H:i:s", 參考 :
    https://docs.djangoproject.com/en/2.2/ref/templates/builtins/#date
  5. slice 的切片用法與 Python 字串或串列切片的用法一樣. 
十年前玩 GAE 時用的也是幾乎一樣的模板語言, 雖然 GAE 當時只支援 Python 2.x 的 Django 0.9 版, 但模板部分那時就很成熟了, 因此也沒甚麼變, Tsung's blog 有整理一篇很不錯的模板語言用法摘要, 參考 :

Google App Engine 初學(8) - 共用 Template (Layout)

兩篇機器學習應用於市場預測之論文

今天找到兩篇機器學習應用在市場預測的研究論文, 值得參考 :
  1. Application of Deep Learning to Algorithmic Trading
  2. Application of Machine Learning: Automated Trading Informed by Event Driven Data
第一篇出自史丹佛大學, 研究者實作了 LSTM 神經網路 (時間序列版的深度學習) 來預測英特爾 (NASDAQ: INTC) 公司的股價, 結果發現 LSTM 模型能更準確預測次日股價, 特別是在盤整的時候.

第二篇是麻省理工學院電機系的一篇碩士論文, 研究者以近十年的 S&P500 指數為對象, 比較了神經網路 (NN), 隨機森林 (Random Forest), 以及支持向量機 (SVM) 三種模型, 發現 SVM 模型有最高的夏普比 (Sharpe Ratio), 即每承受 1% 的波動風險, 可創造 3.5% 的報酬率.

這兩篇深度夠, 但廣度不夠, 因為研究結果只來自於個別標的的訓練結果, 如果能對其他標的重複相同研究, 相信能獲得較一般化的結論.

2019年9月23日 星期一

找回 ESP32 板子收納盒

這兩天發覺平常放在書袋上方的深紫色 ESP32 板子收納盒不見了, 昨晚找遍家裡, 還書袋, 椅子底下, 櫃子全都找過, 就是不見蹤影. 晚上打電話請爸到我書房瞧瞧, 也是沒有. 問說裡面有放甚麼寶貴的東西嗎? 我說就是一些電路板, 算算價值應該有 1500 元吧?

晚上去捷運站載二哥時, 想說先到車上找看看, 雖然早上有大致瞄了一下沒有, 但往裡面摸索很興奮地就在中間走道上尋回了這個紫色盒子, 哈哈哈, 實在太開心了 :




裡面有五塊板子, 真的幸好沒掉在路上. 雖說目前還沒時間回來玩 ESP32, 但若真掉了還得再花千把塊來買就很浪費了, 立馬在盒子上寫上姓名電話, 萬一掉了有心人還能找到失主.

2019年9月22日 星期日

2019 年第 38 周記事

時間過得真快, 輾轉明日就是秋分了, 氣溫也漸漸轉涼, 這幾天晚上睡覺都不開電扇, 還要穿長褲避免著涼了.

早上正準備要去市集時, 聽到有人在門外喊, 出去一看原來是國中同學阿錦來訪, 還帶來一台割草機, 我一看即認出是最近常打廣告的東林電動割草機, 帶來給我看的目的是分享他的創新發想-割草機器人, 他希望我能研究研究 (上回是野蓮收割機), 順便邀我 10 月上雲林參觀農機展. 傍晚打完籃球本想去跑山, 剛好已退休過著雲遊四海好日子的工專同學騎著帥氣的重機來訪, 天南地北一聊就過了六點, 他急忙要趁天黑前返回高雄也沒留下來吃飯. 這鄉居生活有客來訪真的非常難得.

本周陽光先生已看到第 17 集, 具東魅在糖果店前被人開黑槍, 在嚥氣前想到高愛信之前的講過她會毫不猶豫, 難道他認為殺他的是高愛信嗎? 不解一. 另外當鋪的兩位先生幫工藤陽花畫好母親畫像時, 陽花叫他們拿去燒掉, 因為已經不可能找到了, 是早已經死亡嗎? 李正文大人只是說已找到了, 卻沒說已死啊! 不解二. 接下來日本人會施加更多壓力逼迫朝鮮, 尤金的挑戰會越來越大了.





這是第 16 集中尤金與高愛信去釣魚的畫面, 因為高愛信問尤金說 love 從認識, 握手, 擁抱, 思念之後是甚麼? 尤金回答說 : 釣魚.

2019年9月21日 星期六

921 地震二十周年

今天是 921 地震 20 周年紀念, 時間過得好快, 20 年一晃就過去了. 記得那時姊姊才 8 個月大, 我還在中山大學外文系進修, 9 月 20 日晚上我正在熬夜寫英文作文作業, 看看快兩點了正要準備停筆, 發覺怎麼頭有點暈, 是熬夜太晚精神不繼嗎? 我馬上就意會到這是地震, 先呆坐在椅子上兩秒不知該怎麼辦, 這時越搖越大,  我衝去臥室叫水某, 抱起嬰兒床上的姊姊, 但還來不及跑到陽台, 長達 10 幾秒的天搖地動就停了. 我覺得搖這麼大不尋常, 可能還有餘震, 就背了書包抱著姊姊, 一家人走樓梯下到大樓中庭, 這時已聚集許多住戶了. 待了 20 分鐘覺得應該穩定了才上樓看新聞, 原來中部災情慘重.

今天也是母親的五周年忌日.

參加菁菁學校的家庭教育日

今天早上去菁菁學校參加家庭教育日 (就是班親會), 我主要是想認識一下班導, 她說學校樂儀隊老師希望菁菁能參加儀隊, 我馬上敲 Line 問, 勸說明年國慶要上台北表演, 結果她說 No, 因為怕曬黑, 真是傻眼. 會中老師詢問家長擔任家長會代表意願, 還好沒被點到, 我最怕開會了. 哈, 父女都有各自怕的東西, 真是傻眼.

中午回家順路去永茂, 在高醫門口等紅綠燈看到印尼外配在賣印尼便當, 以前路過都沒時間, 今天就下車特地看看她們印尼便當的菜色是甚麼, 大概以炸雞腿與雞翅居多, 我買了一個 50 元雞翅便當回去, 裡面一個雞翅, 一些小魚乾, 辣椒, 還有小黃瓜等等, 感覺印尼人口味偏好辣 :




以前照顧大阿姨的兩位印尼看護妹妹是我最早遇見的印尼人, 每個禮拜拿菜去都會見到, 第一位是家中有許多弟妹, 為了幫助父母維持家計來台灣工作; 第二位則是拋下年幼孩子給父母, 夫妻分赴大馬與台灣工作, 為了家庭經濟她們真的犧牲很多, 而且回教徒很善良, 我們應該將心比心善待他們. 台灣到處都看得到印尼人的身影, 如果沒有他們, 台灣的工程與長照就做不下去了.

翠華路的迷宮

昨天快下班時接到二哥電話, 說教科書發下來了, 紙箱很重, 要我去校門口接他. 以前去高雄大學我都是走博愛路轉崇德路到翠華路的台 17 線, 這回開車我就設定導航, 看看它會怎麼走. 結果看來是要走大中路, 但那裏路網好亂不熟, 所以到崇德路時還是照原路線走.

但是回程就麻煩了, 騎機車可以在大中路高架橋下走地下道, 但汽車不行, 我上回是要直接回鄉下, 所以直走翠華路到蓮池潭後轉回來上國十快速道路, 但這回是要回高雄家. 走台 17 快接近大中路時導航說到橋下靠右上快速道路, 然後靠左下博愛路, 咦, 靠右有閘道嗎? 結果依導航走真的在高架橋下右邊有一個上國十的閘道, 但上去後要靠左才能從中間閘道下博愛路, 靠右是往鳳山與國十.

翠華路與高鐵這邊的路網我一直都覺得很複雜, 平時又幾乎不會走這邊, 要不是二哥讀大學, 我可能一直都搞不清楚要怎麼走. 下次在開車去高雄大學就照導航走看看唄.

2019年9月20日 星期五

市圖還書 6 本

本周市圖還書如下 :
  1. 高手的養成 :股市新手必須知道的3個祕密
  2. 養錢練習 :10大理財好習慣讓你有錢花
  3. 全新!New TOEIC新多益聽力題庫解析
  4. 大學不迷茫
  5. 微積分
  6. 文科生也看得懂的資料科學
大學不迷茫是幫二哥借的, 不過他說沒時間看 (或許沒興趣). 多益也是暑假二哥準備考多益時借的, 後來覺得應該買新的, 就在明儀買了五冊. 我的英文近 10 幾年沒在用心功力大退, 是該補救補救了.

好書 : Computational Physics

因為二哥讀物理, 最近幫他找了幾本 Python 計算物理學的書, 但現在學期中課較忙沒時間看, 先記下來等寒暑假再找來看 :



Source : 博客來


此書是計算物理學書中的上上之選, 內容包括微分, 積分, 解微分方程, 矩陣計算, 傅立葉分析, 動力學,熱力學模擬, 分子動力學, 偏微分方程, 波動方程式, 流體動力學, 量子電動力學, 以及蒙地卡羅算法等等. 只是博客來賣 5000 多元也太貴了, Amazon 才賣 27 元美金耶! 


2. Effective Computation in Physics (Oreilly, 2015)


Source :Oreilly


此書是為物理學相關 (天文, 地理, 大氣科學, 生物, 核工等) 的研究者而寫的 Python 程式工具書. 電腦與數學對物理學而言都只是工具, 沒有他們雖然同樣可以搞物理, 但有了他們就如同猛虎添翼. 此書比較偏向物理人的 Python 資訊處理工具書 (例如 Numpy 陣列, 正規表達式, HDF5 資料結構, 版本控制等), 而不是實際介紹物理方面的應用, 書中不會介紹如何用 Python 解波動方程式. 這本有簡體翻譯版, 參考 :

Python物理學高效計算




Source : CRC


此書與上面第一本內容類似, 包含物理學各領域, 但著重在如何從理論式轉換到程式化的過程, 每章末尾附習題, 屬於嚴謹教科書.

另外我在下面這篇找到五本書, 但其中只有第一本 Mark Newman 寫的 Computational Physics 使用 Python :

5 Highly Recommended Computational Physics Textbooks

4. Computational Physics (2012, CreatedSpace)


Source : Amazon


此書為 2012 年出版, 應該是使用 Python 2.x 版.

總之, Python 在計算物理學上的應用幾乎是建立在 Numpy, Scipy, Pandas, 與 Matlablib 這四個重要套件上, 事實上, 不只是物理學, 只要是量化計算, 精通這四個套件是基本要求.

我想找中文 Python 計算物理學的書, 除了 "Python物理學高效計算" 這本檢體翻譯書外竟然付之闕如. Amazon 倒是有一本日文的 :

計算物理学II ―物理現象の解析・シミュレーション― (実践Pythonライブラリー)

其實英文的本就不多了, 何況是中文.


2019-09-20 補充 :

找到一個 Scipy 線上教材 :

Scipy Lecture Notes

2019年9月19日 星期四

2019年9月18日 星期三

上面種電下面種瓜

今天看到今周刊這篇農電, 魚電複合式經營的文章, 覺得綠色能源過去是因為不做, 所以讓擁核者頻頻用缺電當作裹脅人民的工具, 明明就沒有一個鄉鎮願意當核廢料掩埋場, 偏偏就一堆腦袋進水的要推核能. 只要政府政策明確, 配套法規都能完善, 南臺灣炙熱的太陽就能轉化為源源不絕的能源, 底下又能進行能耕, 不影響農地農用原則.

上面種電、下面種瓜 他年收3千萬 台灣太陽能兆元商機爆發

大約三年前就得到屏東向陽公司的資訊, 一直想找時間去參訪都未成行. 一公頃土地電廠年收入 500 萬元, 農作收入 250 萬元, 業者六公頃年收就超過四千萬元, 不過這是自己投資建設才是如此, 裝置成本應該很可觀. 如果只是租給維運商一公頃收入多少要再探究.