如何用 Python Flask 框架快速建立網站        --   by 蔡文能 tsaiwn@cs.nctu.edu.tw    
*** 想玩 IoTTalk 物聯網應用可以先 點這看 IoTTalk 物聯網應用操作入門
        如果你是可能的 IoTTalk 系統管理者, 可以點這看 IoTTalk 系統開發者手冊   
根據TIOBE 的程式語言使用排名, 現在(2019/01) Python 語言 已經躍居排名第三的程式設計語言!
    ** Python 語言在 2007, 2010, 和 2018 三度入選程式語言名人堂(Programming Language Hall of Fame)   在IEEE排名第一
    ** 在用於資料分析的語言當中, Python 語言也已經躍居排名第一佔比持續上升當中     Python vs. R   有人唱衰Python   Julia竄起
 
現在我們要來看看Python+Flask 弄個網站有多簡單.. wOne   wTwo   WWW(含templates與static)  
      ( 若還不太懂 HTML 可先點這看我很久很久以前寫的超簡單 HTML 網頁教學, 大一計概講義 )
  ==> 已經會一點 Python 想看看 Python 物件類別以及模組 與 套件等重要概念請點這跳到後面
👉 50 cnn Python 入門(會往下跳約四頁) ; 順便教大家至少四種執行Python 程式的方法 ..
      (有問題問StackoverflowQuora大陸SegmentFault 就對啦 !)

* ? 堆疊Stack vs. Queue佇列   ( Stack Overflow ; 堆疊溢位去stackoverflow問 ) (大陸什麼都抄 S.F.)
      ? 堆疊StackQueue佇列 都是很重要的資料結構(Data Structure); 可以用Python學基本資料結構
      ? 電腦程式和一些相關術語(Terminology / Glossary)   Acronym 頭字語 and TLA
* 假設你的伺服器(建議 Ubuntu Linux, 但別的也 OK)已經 安裝了 Python3.5+ 以及 ..
    以及 Flask 框架(Framework); 所謂框架, 簡單說就是比 Library 好用且通常是為某個特定目的寫得差不多了 :- )
** 伺服器 (Server)其實跟你的電腦沒啥差, 你自己的電腦也可當作伺服器 !
** 現在有很多 雲端情人 .. 阿不是, 我是說 雲端伺服器, 且通常一部電腦"變出"很多部來賣給很多人,
      所以稱作"虛擬個人伺服器"(Virtual Private Server; VPS),
      有些可免費試用兩個月甚至一年, 想自己弄一部 VPS 虛擬伺服器來玩的點這裡看說明(要有信用卡)  
**   要從 PC/Windows 連接到伺服器做事, 通常需要有SSH 遠程連線工具, 就是以前玩 BBS 的連線工具但有加密的啦
        如果你的 PC/Windows 沒有 SSH 遠程連線工具, 可以 捲到最後抓 PuTTY 或 PieTTY(在最底下有連結)
    *** 通常 PuTTY 需要安裝, 但安裝就需要有 Administrator 權限(除非找到綠色版, 但綠色版大多是老共做的怕怕的:-)
    *** 台大學生林弘德 從 PuTTY 改來的PieTTY 則不需要安裝, 解壓縮後就可使用(缺點是 PuTTY 更新後 PieTTY 不一定更新:-)
**   如果你沒有Unix機器可以用, 可暫時用我這 iottalk.vip 上提供的兩個帳號;
    這機器上已經安裝好 Python3 和 Flask, 所以你登入後就可照這邊教的做練習 :-)      
    可用 SSH 工具(PC/Windows 可用 PuTTY 或 PieTTY)等連入 iottalk.vip 然後帳號用 test38 或 test49
    密碼都是 1234 ( 連線時直接打 test38@iottalk.vip 或是連入後再打帳號也可 )    

    如果你是用 Mac OS, 可以用內建的 Terminal (終端機) 下達 ssh 命令即可, 例如:
            ssh 你的帳號@iottalk.vip
    連入後, 如果不太會用 vim/vi 那就用 nano 編輯文字檔 (只要記得 CTRL_S 存檔和 CTRL_X 離開:-)
  Mac OS 其實也是一種 Unix
  Unix/Linux 常用指令(命令)大全
  Linux常用指令(Windows安裝 git 就有喔)
  GNU/Linux常用指令(ubuntu Linux 手冊)
  GNU 是啥碗糕 ?(GNU is Not Unix)
  Linux 又 是啥碗糕 ?(GNU 發啟人認為該叫 GNU/Linux)
  Linus Torvalds(林納斯·托瓦茲) 是誰 ?(Linux 創作者, 芬蘭人)
  Unix 來龍去脈(前身是 麻省理工主持開發的 Multics)
  古時候還有個 MINIX 喔(by 荷蘭自由大學計算機科學系的塔能鮑姆教授)
   可以只打機器名稱或 IP ;             也可順便把要登入的帳號先打進去, 如以下右邊的圖:

上右邊圖顯示使用 PieTTY (台大把 PuTTY 拿來改的版本) 準備連入 iottalk.vip 的帳號 test38              
密碼是 1234 請不要改掉, 以免其他人無法測試

 
請注意, 命令窗開啟後, 請立即點最上面"選項"然後把文字編碼設為 UTF-8 或 Unicode,
否則中文字會變亂碼, 程式中有亂碼則編譯會有錯誤! 這是因為預設編碼是 Big5;
登入後, 當然是在"家目錄" (Home Directory), 請大家不要在這建立檔案以免太亂 :-)
就是說請大家"開房間" -- 建立一個你自己要用的子目錄 (當然可以 cd 進入別人子目錄偷看:-)
你現在就可以用 mkdir 造個子目錄, 然後 cd 進入該目錄, 接著 nano w.py 建立檔案
因為這是共用, 子目錄名稱命名請用自己身分證號第一字加後三碼開頭免得和別人撞到 :-)
例如,
      mkdir p007  
      cd p007        
      nano w.py    

nano 編輯文件檔案, 只要記得 CTRL_S 是存檔, CTRL_X 是離開就可, 就是這麼簡單 :-)
對啦, 還要記得可以按上下左右鍵移到你要的位置 :-)
   
     👉   Python 課程很多而且不便宜喔 !
     
      Python Python Python
(一)如果不知道啥是 Python, 看這幾篇: (也可以不要看, 先用再說:-)  

      Python Taiwn Wiki/第一次用就上手
      https://blog.techbridge.cc/2016/12/17/python101-tutorial/
      https://kopu.chat/2017/01/18/一小時python入門-part-1/
      https://blog.liang2.tw/posts/2016/01/lab-coding-python/(Python 初學指南)
      https://openhome.cc/Gossip/CodeData/PythonTutorial/index.html
      http://tw.gitbook.net/python/index.html(Python 基礎教程, 老共)   http://tw.gitbook.net/(很多教學)
      https://www.itread01.com/study/python-tutorial.html (Python 基础教程, 應該是老共寫的) 啥是內容農場
      翟天臨網路聲量遠大於韓國瑜 (怎放這東東 ? 阿證明上一篇是老共寫的啊 ! 呵呵 ! 蘇東坡說的: :-)

                  數位時代批評內容農場(content farm), 自己卻惹人討厭(進入網頁突然冒出聲音)


      https://docs.python.org/3/tutorial/ (官方網站文件)               https://www.programiz.com/python-programming/tutorial (好站)
      https://www.w3schools.com/python/ (也是好站)
      https://www.tutorialspoint.com/python/ (很詳細)  

      **也可以到這 https://repl.it/languages/python3 線上輸入 Python 程式碼測試
  👉 這有人在 REPL.IT 用 Python 寫了一個無聊小遊戲ㄟ(十六歲高中生寫的)
         *這也是在 REPL.IT 一個無聊小遊戲(應該是同班同學的學生練習題😗😇)
  =====> 點這往後跳看看她學姐用Python在 REPL 寫小說但沒防呆
         *還有這超笨的井字遊戲(純 Random 選 沒 AI)
         *有人用 Python 寫了 Othello 黑白棋遊戲(Github) 這比較複雜:-(
      ***關於 REPL.IT 介紹請點這   或   看 Youtube 影片介紹 REPL.IT (其實不用看直接用就對了啦:-)

 
      Flask Flask Flask
(二)如果不知道啥是 Flask, 看過來..         
     

*Flask vs. Django:Why Flask Might Be Better
           ** Django vs Flask - 7 Amazing Comparison You Need To Know

Flask是一個簡單的網頁框架(Web Framework), 它使用 Jinja2 樣版(Jinja2 Templating)
Flask 設計者認為一個網站就是該針對溜覽者的需求(Request)給予適當的回應(Response),
所以, Flask 的設計目標是讓以前的 FORM / Action / CGI 的設計方法變得直覺又自然 ! ( 有人蒐集了 CGI 教學 )
事實上, Flask 對這點也確實做到了 ! 等下我們用實際的範例來驗證做個網站有多簡單!!!
你也可以先 點這連到 Flask 官方網站, 大略看看官方文件怎麼說 :-)
           
* 第一個網站範例來了.. (假設已經安裝 Python3 和 Flask)
    ** 用 遠端連線工具如 PuTTY 或 PieTTY 甚至 ssh 等連入伺服器 (在最底下有連結)
    ** 然後, 你先建立一個子目錄, 名稱隨意,
    ** 在該子目錄內建立一個Python檔案, 名字也可隨意取, 偷懶點,
    我們就叫 w.py 好了 (以下使用 nano 這超簡單的 text editor 文字編輯器)
         
    補充說明: 在 nano 內可隨時敲 CTRL_S 存檔, 敲 CTRL_X 結束離開 !
          ** nano 原意是十億分之一(10的負九次方), nano meter 就是奈米(10的負九次方公尺)
          ** mkdir mywww 表示建立 mywww 這子目錄, cd mywww 表示進入 mywww 這房間(子目錄)
          ** mkdir mywww 表示 make directory
                  cd mywww 表示 change directory
 
    檔案 w.py 內容如下: (你可以使用任何 editor 文字編輯器如 vim / vi / nano 等)
### w.py     # coding=utf-8
from flask import Flask
app = Flask(__name__)

@app.route("/")
def webRoot( ):
   return '<font color=Red size=7>Hello World!  &nbsp; &nbsp; 這是網站喔 !</font>'

app.run( '0.0.0.0' , port=5566)
    這就是一個簡單網站了, 只要六行(註解和空白列不算), 厲害吧 !? 馬上把它跑起來(執行起來), 用這命令:
        python3 w.py  

     

      現在開啟瀏覽器, 在網址列打入如下: (這裡假設我們的伺服器名稱是 iottalk.vip )
        iottalk.vip:5566  
      上面的網址是可以點的, 但事實上我聽 Port 5565 不是 5566 喔 !
   
看到網頁了ㄟ !
      全世界都在看 .. 阿不是 .. 我是說 ..
      在全世界都可以用喔 ! 如果你的終端機都不關, 這網頁就永遠存在 !
      或者把剛執行 Python 的命令改如下: (就是尾巴多打個 & 符號)
          python3 w.py   &  
      然後即使你登出帳號, 甚至關閉終端機, 只要我這伺服器開著這"網站"就永遠存在 !
      只是, 這網站也太陽春太無聊了 :-)
* 如果你是在自己電腦上(PC Windows or Mac 都可)跑這個程式,
      那只要開瀏覽器打 127.0.0.1:5566   (千萬不要呆呆的打 http://0.0.0.0:5566 喔!)
      或找出你的 IP, 然後用你的 IP 取代 127.0.0.1   也可以 !
==> 如何找出自己 電腦 的 IP ?
   => Windows 只要在 CMD 窗打入這命令: ipconfig
   => Mac OS 可打 ipconfig getifaddr en0
       ( 必要時把後面 en0 改用 en1   -- 就是數字 0 改數字 1 )
   => Linux / Unix 系統請打 ifconfig
    或打   ifconfig | grep inet | grep mask

  * 如果發現執行失敗但你確定程式碼都沒打錯, 注意看一下錯誤訊息, 可能是 Port 被佔用
    那就改一下程式碼內的 Port 號碼, 原則上 1024 到 49151 都可以用 !
    啥 ?可不可以不要打 Port 數值喔?
      阿在網址列不打 port 就等於打 :80, 可是 0 ~ 1023 規定必須有 root 權限(root privilege)才可以用 !
      所以如果在你的 python 不打只是寫 app.run( ) 則會自動使用 Port 5000
      當然如果是在你自己的 Windows 系統下可能就愛怎麼用都可以沒任何限制 :-)
  * 所謂的 root 權限 是 Unix 這類系統上系統管理者的權限, 因為 username 是 root,
      也就是 Windows 系統上的 Administrator 啦 !
  
小提示:
* Unix/Linux (包括 Mac OS)系統內建 第二版的 Python, 所以自己安裝的通常是 python3  
* 使用 Python 通常建議建立虛擬隔離環境(Virtual Encironment)在裡面做事:
* 要建立隔離的虛擬環境很簡單: (所有 Unix/Linux 以及 Mac OS 通用)
mkdir haha  # 造一個子目錄 haha (不造也可以, haha 是自己隨便取名的)
cd haha   # 進入 haha 子目錄準備開始工作
python3 -m  venv myvenv    # 會建立子目錄 myvenv, 是一個 Python 虛擬環境
source myvenv/bin/activate  # 啟動虛擬環境
**Windows 系統則上述的最後 source 那句 改如下 : 
     myvenv\Scripts\activate
   (其它三句一樣, 當然在 Windows 打 python 即可,不必打 python3)
     然後, 你可以 cd 切換到別的目錄做事, 不必在 myvenv 內啦 ! 
大提示: (for using Python on Windows)
 
** Windows 安裝 Python 後不能用 ? 
    如果安裝 Python 時忘了勾選 "Add Python 3.x to PATH", 
    當然就不能用囉 !
** 解決方法
  ==> 建議直接砍掉重新安裝比較快 :-) 

**如果你堅持要修改系統的 PATH 命令路徑.. 
(0)先找出你的 Python 安裝目錄, .. 
   假設是  "C:\Program Files\Python37\" 
  則你必須把以下兩項目錄加入你的 PATH 命令路徑 :
   C:\Program Files\Python37\Scripts\;C:\Program Files\Python37\ 
(一)Windows 7 電腦 
  (1)找到 "電腦" 或 "我的電腦", 按滑鼠右鍵選 "內容"
  (2)點進階系統設定
  (3)點進階分頁下方的環境變數
  (4)從系統變數中找到Path,雙擊滑鼠左鍵編輯Path
  (5)到該格子最左邊 (要很小心!) 輸入以下(複製貼上, 含最後的分號):
C:\Program Files\Python37\Scripts\;C:\Program Files\Python37\;
  (6)仔細檢查, 原先的不可破壞, 否則要找厲害的同學幫忙修復很麻煩!
    檢查正確後, 點 "確定" 
  (7)重開 CMD 窗輸入 python --version 看看
(二)Windows 10 電腦
  (1)在左下角的開始選單, 輸入 "環境變數" 搜尋
  (2)選擇 "編輯環境變數"(控制台)
  (3)點進階分頁下方的環境變數 (與 Windows 7 類似)
  (4)從系統變數中找到Path,雙擊滑鼠左鍵編輯Path (或點編輯)
  (5)點小窗中右上角的"新增", 加入以下兩個路徑: 
C:\Program Files\Python37\Scripts\
C:\Program Files\Python37\ 
  (6)Windows 10 是逐項加入, 所以不必打最後的分號
   建議新加入的放最前面讓系統最先搜尋
  (7)重開 CMD 窗輸入 python --version 看看
TOP        
     

蝦密 !? 不懂 Python 和 Flask 語法喔!?
Ans: 先不要管語法(文法)啦, 你小時候學講話有先學文法語法嗎?
     直接看範例改範例, 遇到問題就問 Gogle.com 這 GOOGLE 大神 :-)
         The syntax of the language Python is clean and length of the code is relatively short.
     It's fun to work in Python because it allows you to think about the problem rather than
     focusing on the syntax.

     啥?  HTML 網頁語法也不懂?
Ans: 也沒關係啦, 阿就先參考範例+多看看別人作品不小心就會了:-)       
     可以 先點這看我古時候寫的超簡單網頁基本教學(不到十句語法)。
     阿不然 點這到 https://www.w3schools.com/ 看 HTML 網頁教學
     或是 點這到 http://www.cg.com.tw/ 有很多教學文件

     啥? 聽說 DreamWeaver 用來做夢 ....  阿不是.. 是 說 用來做網頁很好?
     阿就點上面 http://www.cg.com.tw/ 裡面有教學 !

     其實在  w3schools.com 內也有個讓你線上立即打入並測試網頁的喔 !

     還有, 這個線上 HTML Editor 可讓你雙向修改查看 網頁樣子 與 網頁原始碼
     還有, 這個線上 HTML Editor 可讓你雙向修改查看 網頁樣子 與 網頁原始碼
     還有, 這個線上 HTML Editor 可讓你雙向修改查看 網頁樣子 與 網頁原始碼
     (尼采說:很重要, 所以說三次:-))
   
     
網路傳奇小故事 -- ICQ --- 還好除以三除不盡 :-)

      話說 1996年11月, 網路開始流傳一個叫做 ICQ 的軟體(諧音 I Seek You 我找你), 免費下載註冊, 當時大家見面就說: ㄟ 你的 ICQ 號碼給我啦(剛開始註冊是六位數號碼), 啥? 你沒有, 趕快下載註冊啦。
      這個 ICQ 是所有即時通訊(Instant Messenger)軟體的始祖, 隨後1998年陸續推出的的 Yahoo 即時通(1998年3月) 和 微軟的MSN(1999年7月發表;很多人聽到"等登燈"聲音就會精神為之一振:-)等, 可以說都是抄襲 ICQ 啦; 至於後來2003年8月問世的 Skype 則又是另外一種創新(以後再來講這故事), Skype 不但可以打字, 也可以講話, 甚至陸續加入多方通訊、網路開會等功能。 後來2006年開始進入智慧型手機時代,這些就漸漸被 Whatsapp、LINE、WeChat 等取代了。

Me too .. Me two .. Me 2 .. Me 3 ..
由於 ICQ 這個當時的 Killer Application 轟動世界驚動武林, 全世界都在抄襲它 ..
台灣有人搞 CICQ (資迅人一開始 IQ搜尋家還不錯, 接著搞 CICQ, .. 後來燒光投資人的錢.. 於2001年4月,資迅人因股東不願再加碼投資,資金燒完後,負債1億元倒閉 ), 大陸有人搞了 QQ (所以大陸人見面就說 Q 我 Q 我), QQ 的公司就是現在大陸很有名的騰訊公司。 (其實就是馬化騰看到了 ICQ 才在1998年11月成立的公司)世界知名遊戲 LoL(英雄聯盟) 的公司Riot Games 拳頭公司 在2015年12月被騰訊蒐購。
* Chineasy 看中國大陸的社群媒體 (註: 這是原先資迅人創辦人之一薛曉嵐創立的網站)

      大約一年多後, 台灣 網路討論群(Newsgroups, 類似BBS)上有個人發表一篇貼文:
大家安安 ...我的 ICQ 號碼是 1000xxx 請大家加我窩 ...

隨即有人 follow up 說到: 你頭殼壞掉, ICQ 號碼只有六位數, 怎你的有七位 ???
有個人: 你才頭殼壞掉, 現在 ICQ 已經進化到七位數了你都不知道 ...

      一開始 ICQ 是以色列特拉維夫的 Mirabilis 公司放在網站讓大家免費下載使用,該公司由四位以色列青年: Yair Goldfinger、Sefi Vigiser、Amnon Amir、Arik Vardi 共同創立於1996年7月,由 Arik Vardi 的老爸Yossi Vardi(尤希.華地)擔任老闆(因為他投資最多)。
  註: 尤希.華地(Yossi Vardi)說他一開始其實也不知道他兒子搞那個 ICQ 是幹啥的有啥鳥用:-)
大約1997年4月, Amnon Amir 質疑公司從1996年7月創立至今都沒收入還提供免費 ICQ 到底在幹啥? Vardi 跟他說: 要相信我, 我們會賺大錢啦!
可是 Amir 堅持要退出, 後來 Vardi 就說那好吧, 你的股份除以3分別賣給我們三位.. 計算器打一打, Vardi 說: 除不盡ㄟ.. Vardi 說: 阿那除不盡剩下那一點點你就留著啦 !
因為 Amir 退出, 所以網路上有些文章會說 Mirabilis 公司是以色列三位青年創立 ! (有些說四位)

1997年6月:以色列Mirabillis公司被美國AOL收購,改名ICQ公司。
      兩個月後的 1997年6月, 各大媒體登出一則大新聞:
美國AOL用 2.87 億美金收購 以色列Mirabillis公司(並將之改名 ICQ公司), 2.87億是前金, 另外附帶看表現另給後金1.2億美金)。
當時所有媒體以及名嘴都說 AOL (American OnLine, 美國線上; 類似台灣的 Hinet)頭殼壞掉, 竟然花那麼多錢買一家全球只有一千兩百萬會員(我也是其中一個會員ㄟ)且沒賺錢的網路公司 !?
Amir 很高興: 幹..還好除以3除不盡 ! 因為他竟然莫名其妙也變富翁 :-)
過了大約半年, AOL 股價漲了十幾倍, 所有媒體和名嘴又改口了, 都說:



這時的 AOL 風光一時, 2000年1月,AOL顛覆以往併購的模式,以小吃大併購時代華納。
*** 這時大家終於相信:只要能蒐集夠多會員, 你的網站就會很值錢 !!!
不過隨後自2000年3月開始發生 dot com Crash 然後 AOL 又沒好好利用 ICQ .. 於是..
* 2002年, 合併後新公司大賠近1000 億美元,創下史上企業最大筆的虧損...
* 2009年,AOL正式與時代華納分離,成立獨立公司並將標識改為「Aol.」。
* 2010年4月 AOL 把 ICQ 以1.875億美元賣給俄羅斯DST公司
* 2015年4月電信商Verizon以44億美元收購AOL
* 2016年, AT&T 以854億美元(約新台幣3.46兆元)收購時代華納公司(Time Warner)
* 2017年6月美國電信公司Verizon以44.8億美元收購雅虎的網路服務
    2008/02/01,全球電腦軟體龍頭老大微軟公司宣布,將以446億美元(約1兆4352億台幣)併購網路公司雅虎
    但是雅虎嫌太便宜後來不賣。 (2000 年 1 月 3 日, 雅虎的市值一度達到 1280 億美元 。)

* 雖然 2000年3月開始發生 Dot Com Crash, 很多科技公司倒閉, 甚至當時搜尋引擎的 Me too Google.com 差點倒掉, 去拜託 Yahoo! 用 200萬美金買下, Yahoo! 覺得阿我自己就是搜尋引擎始祖幹嘛買個要死不死的小孩子 !? (還好後來 Google 獲得另一筆資金投資!) 不過, 蒐集夠多會員然後轉賣的例子不斷出現:
** 2002年10月,全球最大拍賣網站eBay以15億美元收購PayPal,Paypal是成立於1998年12月。
** 2003年7月 Myspace 公司成立, 很快成為全球最多人用的社交網站, 到 2005年7月被新聞集團(News Corporation)以5.8億美元買下(當時活躍用戶2200萬, 在此同時 Facebook用戶約800萬), 不過到了2011年6月新聞集團斷尾求生把 Myspace 以3500萬美元賣給 Specific Media 公司。
** 2003年8月網路出現另一個 Killer Application 叫做 Skype, 利用轉繞技術讓網路語音通話變通暢, 2005年9月eBay 用41億美元(26億美元現金+eBay股票15億)買下 Skype 公司。 到2011年5月,eBay 把 Skype 以85億美元轉賣給微軟(Microsoft)公司。
** 2005年陳士駿(1978/8/18出生在台灣)已經從Paypal公司(1998年成立)退休, 在一次同學會之後創立了Youtube公司, 到了 2006年10月被Google以16.5億美元收購。
** 2009年 WhatsApp 出現在智慧型手機, 很快成為最流行的即時通訊軟體, 到了 2014年2月臉書(Facebook)宣布用193億美元收購了WhatsApp公司。
** 2012年4月9日, 臉書Facebook宣布以10億美元的價格收購Instagram公司
** 在交大資工系內的無名小站, 到2004年時會員有20萬人, 2005年3月由「甲伯伯」賈文中投資新台幣2000萬成立「無名小站公司」, 到了2006年12月由Yahoo!以台幣7.2億元收購, 「甲伯伯」個人賺到三點六億, 根據合約, 雅虎應該付給交大兩千萬衍生利益金, 另外由於無名小站成員看到錢就忘了仁義道德, 引發了蔡神大戰丁丁的網路風波 ! 無名小站嫁入Yahoo! 曾經風光數年, 但是七年後, 到了2013年12月26日無名小站正式終止服務。 (對啦, 這裡說的蔡神就是敝人在下個人我啦:-)
網路就是這樣, 凡走過必留下痕跡:-)   Growth Hack   成長駭客(YTb) 成長駭客Book(YTb)   增长黑客(YTb)   哈佛幸福課(YTb)

**在交大計中內的PIXNET是由交大工工系4年級的曾皇霖和交大外文系2年級的劉昊恩在2003年9月共同創立, 2004年12月開始提供BLOG部落格服務, 到2006年4月初趁著春假PIXNET由交大計中移往台北正式商業化, 到了 2007年3/12香港城邦媒體控股集團以台幣一億多一點入主PIXNET, 並將公司中文名稱訂為「痞客邦」,到了2013年,痞客邦超越無名小站,成為台灣最大的部落格網站。(無名小站在2013/12/26關閉) 目前 PIXNET 流量在台灣僅輸給 Google, 在全球排名則大約在一百名左右 ! 也可以點這看 PIXNET 在台灣網路流量排名。(第一名Google, 第二名Youtube 仍算Google, 第三名就是 Pixnet痞客邦。
雖然爆料的Blog不見乃特工作室早就關閉了, 但是關於法鵝大站(就是PIXNET)的報告永存網路 上面(蔡神註: 我寫的報告早就 奉命銷毀了 :-) 。 


根據報導, PIXNET 痞客邦在賠了三億後終於自2016年起轉虧為盈開始賺錢 !
* 在痞客邦寫文章可以賺錢但會被 PIXNET 抽頭, 這有人寫了經驗文
    (不過有個退休國文老師每天寫文章罵政治人物據說每月從Google賺到廣告收入八萬多元)
* 台灣數位廣告量每年超過 330 億台幣

* 這即時通訊軟體的始祖 ICQ 還沒死, 它在俄國其實還很流行喔,
    而且 ICQ 還已經變成 Open Source(開源軟體):
          https://github.com/mailru/icqdesktop
Yahoo     Google Blogger     蕃薯藤 天空部落     Xuite 隨意窩     Pixnet 痞客邦
TOP              
     

      ** 第二個網站範例來啦 . .

      現在來建立第二個網站範例, 檔案就叫做 w2.py 好了, 內容如下:
          (複製貼上貼到你的 nano 編輯視窗內 然後敲 CTRL_S 存檔即可用)
### w2.py  # coding=utf-8
from flask import Flask
app = Flask(__name__)

@app.route("/")
def webRoot( ):
   return '<font color=Red size=7>Hello World!  &nbsp; &nbsp; 這是網站喔 !</font>'

@app.route("/hello")
def hello():
   from datetime import datetime
   ans = '''   <meta name="viewport" content="width=device-width, initial-scale=1.0">
       <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
   '''
   ans += "<font color=blue size=5>Hello there!<br> 現在時間是 {}<br>我是 {}".\
   format( datetime.now( ).strftime('%Y-%m-%d %H:%M:%S'),
    "009008007 張大千"  )
   ans += '''<br>簡單吧!?<hr>
     <a target=_blank href="https://iottalk.vip/static/ab.html"
     >點這玩我用JavaScript寫的電腦猜人想的幾A幾B(Bull & Cow 公牛母牛)遊戲</a>
     <img src="https://media1.tenor.com/images/144d0621c5ccab3f9f22d6581e9b9801/tenor.gif"
         style="width:46vw">
     <img src="https://media1.tenor.com/images/77853b2777e59f0b09de447ba94638cd/tenor.gif" style="width:46vw">
     <hr style="border-top: 3px dashed blue">
     <hr style="border-top: 3px dotted green">
     <hr style="border-top: 3px solid red">
     '''
   return ans

app.run( '0.0.0.0' , port=5566)
      也是馬上把它跑起來(執行起來), 用以下這命令:
      (剛才第一個範例必須敲 CTRL_C 停止執行喔! 阿不然 Port 5566 已經被佔用了 )

      如果你自己沒佔用該 Port, 但系統說被佔用, 那就是剛好別人也在測試啦 :-)
          python3 w2.py  
        現在到任何電腦開啟瀏覽器,
        在網址列打入如下: (這裡也是假設我們的伺服器名稱是 iottalk.vip )
          iottalk.vip:5566  
        蝦密 !? 差不多一樣喔 !? 別緊張, 到網址列尾巴補上 /hello 然後按下 Enter 鍵
        就網址列的命令改如下:
          iottalk.vip:5566/hello  
        不一樣了吧 !? (上面兩個網址也都可以點, 但是我是聽 5567 不是 5566 喔)
        網頁裡面有文字也有圖片ㄟ .. 還有那個川普在耍寶 :-)
        你也可故意把瀏覽器的視窗拉大拉小看看內容是否有變化 !
   * 提醒: Port 5565Port 5567 都已經被我佔用喔 !

在 Unix 裡面有個萬年曆程式, 命令是 cal
打入 cal 就會看到這個月的月曆, 打 cal 2019就是今年的各月月曆,
請打 cal 1752 年看看 1752 年月曆, 仔細看9月的地方, 你會發現當年九月只有 19 天喔 !


注意看九月份 !
點這看為何1752年九月只有 19天 !? (啥, 9/2 隔天就變 9/14 ㄟ !)
還有,
大家都知道中華民國元年一月一日是1912/01/01,
但是很多人不知道該天的前一天是1911/12/18, 你知道嗎?
這是因為世界各國的曆法切換日並不相同 !!
你可以使用 ncal -p 命令查看各國曆法切換的前一日, 例如,
   IT Italy     1582-10-04   義大利, 隔日為 10/15
   JP Japan     1918-12-18   日本, 隔日為 1919/01/01
ncal -p
ncal -s IT 1582
ncal -s JP 1918
另外, 可以點這看關於儒略曆(Julian calendar)與1582後的格里曆(Gregorian calendar)之故事

TOP              
     

    *** 第三個網站範例來啦 . .

      啥 !? 剛那 w2.py 的網頁裡面都不能點喔 ?!
    對啦, 那就來建立裡面有可以點的超連結(HyperLink)第三個網站範例 w3.py,
    檔案 w3.py 內容如下:
### w3.py  # coding=utf-8
from flask import Flask
from flask import render_template

app = Flask(__name__)

@app.route("/")
def webRoot( ):
   return '<font color=Red size=7>Hello World!  &nbsp; &nbsp; 這是網站喔 !</font>'

@app.route("/hello")
def hello():
   from datetime import datetime
   return "<font color=blue size=5>Hello there!<br> 現在時間是 {}".\
   format( datetime.now( ).strftime('%Y-%m-%d %H:%M:%S')  )

@app.route("/haha")
def giveHaha():
   return '''<center><b><font size=7 color=blue>搖 頭 大 集 合</font></b></center>
    <img src="https://media0.giphy.com/media/5xaOcLGvzHxDKjufnLW/giphy.gif" width="33%" style="float:left;margin-left:18px">
    <img src="https://media.giphy.com/media/c6rJJ6NXpLLyg/giphy.gif" width="23%" style="float:left">
    <! img src="https://media0.giphy.com/media/jzaZ23z45UxK8/giphy.gif" width="38%" style="float:left">
    <img src="https://iottalk.vip/static/images/ggg2.gif" width="30%" style="float:left">
    <hr style="border-top: 33px solid gray">
   '''

@app.route("/add/<int:a>/<int:b>")
def getAnsMD(a, b):
   ans = a + b
   out = '''<b><font color=blue size=7> The answer  of {} + {} is  {} <br>
  <font color=red> &nbsp; while {} - {} = {}
   '''.format(a, b, ans, a, b, a-b)
   return out

@app.route("/hehe")
def helloeee( ):
   return '''<meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
   <body background="http://img.zcool.cn/community/0163015926a71da801216a3e8b8916.jpg">
   <b><font color=blue style="font-size:2.8vw">
    <font color=darkRed>Hello World!  &nbsp; &nbsp; 這是RWD網站喔 !</font>
    <br><img src="https://media.giphy.com/media/c6rJJ6NXpLLyg/giphy.gif" style="float:left">
    <img src="https://media2.giphy.com/media/3o6ZtgnmZDZeAshxYY/giphy.gif" style="float:right" width="28%">
   <font color=blue><a href="http://www.edu.tw">點這連到教育部</a>
   <br><a href="http://mit.edu">點這連到 MIT 麻省理工</a><br>
   <br><a target=_blank href="http://8maple.ru/100369/">點這開新窗柯南線上看</a><br>
   <br> <br> <hr style="border-top: 3px dotted blue">
   <br><img width="30%" src="http://gif-finder.com/wp-content/uploads/2016/02/Brazilian-boy-and-dog-samba-dance.gif"
       style="float:left">
   <img width="30%"
       src="https://vignette.wikia.nocookie.net/scream-queens/images/a/a7/3d-animated-girl-dancing-6.gif/revision/latest"
     style="float:right">
   <img width="30%" src="https://i.pinimg.com/originals/fe/a9/52/fea952713e7bbd99e68f53b688f9cf15.gif" 
      style="margin-left: auto; margin-right: auto;">
   <br> <br>
    <img
    src="http://gogonews.cc/article/img/2018/08/01/iyMPyzf6M511yvS/qy0LHRM1MJAU.gif" style="margin-left:8px;width:33vw">
    <img src="https://i.gifer.com/7yVI.gif" style="float:left;width:32vw">
    <img src="https://thumbs.gfycat.com/CreamyUnacceptableAnura-size_restricted.gif"  style="float:right;width:32vw">
   '''

@app.route("/hello/<string:name>/")
def hello2(name):
   return render_template( 'test.html',name=name)   # name 會傳進去給 test.html

if __name__ == "__main__":
   app.run( '0.0.0.0' , port=3388)
這次不用說如何測試了吧 !?
啥!? 你測試發現沒效喔 !?
  那你先點這裡測試我的 w3.py(但我用 Port 3389)
ㄟ, 阿那個你知道為何你的沒效了吧?
      你沒注意到網址列的 5566 該換成 3388 對吧? 就是說..
        在網址列要打入如下: (這裡也是假設我們的伺服器名稱是 iottalk.vip )
          iottalk.vip:3388  
    還有這:
          iottalk.vip:3388/hello  
       
    以及這:
          iottalk.vip:3388/haha  
       
    也測試這:
          iottalk.vip:3388/hehe  
       
    它還會做加法減法喔:
          iottalk.vip:3388/add/12568/333  
ㄟ .. 當然不是只有會這兩個數的加減法, 你可以把網址列後兩個數值換別的試看
         
==>   再來測試這個看看: ( 就是在 /hello 後面打斜線 並繼續打一個字串 )
          iottalk.vip:3388/hello/張大頭  

    啥 !? 有問題喔 !
    對啦, 因為少了一些檔案(2個檔案):
          templates/test.html     和     templates/layout.html


    馬上建立一個子目錄 templates (注意, 不是 template 喔, 尾巴有 s 喔!)
    然後用 cd templates 命令進入該子目錄,
    在該子目錄內 建立以下 layout.htmltest.html 兩個檔案:
 <! layout.html   小於號緊接著驚嘆號空隔是HTML單列式註解用大於號結束 >
<title>Website</title>

<style>
@import url(http://fonts.googleapis.com/css?family=Amatic+SC:700);
body{
    text-align: center;
}
h1{
    font-family: 'Amatic SC', cursive;
    font-weight: normal
    color: #8ac640;
    font-size: 2.5em;
}
</style>
{% block body %}
{% endblock %} 

 * 注意, 檔案編碼請用 utf-8 否則中文字會有問題喔!

 <! test.html    小於號緊接著驚嘆號空隔是HTML單列式註解用大於號結束 >

{% extends "layout.html" %}
{% block body %} 
<div class="block1">
<h1>Hello {{name}}!</h1>
<h2>Here is an interesting quote for you:</h2>
"The limits of my language are the limits of my mind. All I know is what I have words for."

<br><font color=darkGreen size=4>
"我只是一條蛇, 你能期望我會懂蝦密碗糕呢 !?"</font>
<img src="http://bestanimations.com/Animals/Reptiles/snakes/green-snake-animation-3.gif" style="float:left">
<img src="http://animationsa2z.com/attachments/Image/snake/snake4.gif" style="float:left">
<img src="http://www.naturalprogramming.com/images/smilingpython.gif" style="float:left">

<img src="https://mshiamcom.files.wordpress.com/2016/05/snake-gif-animation.gif" 
    style="position:fixed; left:158; top:168;z-index: -99; ">
<hr style="border-top: 3px dotted blue">
</div>
{% endblock %}

 
    好了, 馬上回到上一層目錄(用 cd .. 命令回上一層, 就是 w3.py 所在的目錄) 重新測試看看 !
    上面這招套用樣版(render_template)的部分是參考了以下教學網頁:
       https://pythonspot.com/category/pro/web/flask/


Q: 我有純網頁的檔案, 可以簡單放入這種網站嗎 ?
A: 可以啊, Flask 預設如果檔案放在 static/ 子目錄下的子子孫孫(就是包括子目錄內啦) 一律直接丟到你電腦 !
      這裡說的 static/ 是指在你執行網站 .py 檔案目錄下的子目錄 static (當然這是可以在網站 .py 檔案內設定的)
 
  ** 摘要一下, 所以簡單來說網站目錄結構如下 :
   (Server 端; 此例我們網站根目錄是 ~test38/mywww/)
   ~test38/mywww/w.py,   負責網站的 .py 檔案
                /w2.py, w3.py, ..
                /   
                /templates/ 這裡放會被 render_template( ) 用到的樣版檔
                /
                /static/  這裡放原封不動抓到就丟過去 client 端 Browser瀏覽器的檔案 
   * 註1: 預設(Default)聽 Localhost:5000  也就是 127.0.0.1:5000   (127.0.0.1 代表自己)
   * 註2: templates/ 和 static/  這兩個目錄是可以在網站 .py 檔案內改設定的
   * 註3: Username 左邊放一個彎彎的蚯蚓 (tilde) ~ 代表該 User 的家目錄(Home Directory/ 根目錄)  
         各種『標點符號』的英文怎麼說?
資訊架構(Information Architecture)

根據維基百科,資訊架構(英語:Information Architecture)是在資訊環境中,影響系統組織、導覽、及分類標籤的組合結構。 它是也基於信息架構方法論,並運用內容管理技術來管理和組織信息的一個專門學科。

請不要把"資訊架構(Information Architecture)"翻譯為"資訊結構"以免被誤會為資料結構(Data Structure)),資訊架構算是網站設計的新領域,和資料結構一點關細也沒有喔 ! 資訊架構主要是為了因應網站這個新媒體的蓬勃發展,大量的資訊需要有系統有架構的整理。

資訊架構和視覺設計或程式設計是不一樣的,因為資訊架構關心的不只是網站的外觀,也不是網站的功能(Functionality)。 資訊架構的目的是建立好用、滿足站長/版主,也滿足使用者需求的網站。

所以資訊架構不是美工,也不是程式,而是溝通的技巧與藝術。

簡言之,資訊架構是一種組織和架構資訊的藝術,讓網站使用者不會在網站迷路,讓資訊能夠更簡單且容易地被找到與理解。 所以說好的老師帶你上天堂..阿不是..我是說好的資訊架構是讓網站簡單、清楚、優雅,好用而且很容易使用。

資訊架構師(Information Architect)

資訊架構師的主要工作是組織網站資訊,讓使用者可以很容易找到想要的資訊。 對於電子商務網站,就是要讓使用者在網站停留更多的時間,買更多的東西,讓公司賺更多的錢。

所以,資訊架構師要做的事有:

  • 使用者研究(User Research):使用者想在網站上做什麼事?完成什麼樣的任務?
  • 定義內容(Content)和功能(Functionality):什麼樣的內容和功能可以幫助使用者和組織達成其目的?
  • 發展組織格式(Organization Schemes):網站該如何組織?
  • 和視覺設計或美工設計人員,共同發展介面(Interface)。
  • 監督網站的建置。

雖然資訊架構師通常會規劃出網站地圖(Sitemap),但建立網站地圖並不是資訊架構師最重要的工作。資訊架構師在網站設計團隊(Web design team)中扮演重要的溝通角色, 其最重要的工作是組織資訊並向團隊或上級長官溝通。因為資訊架構師擁有使用者和組織目標的深層知識,必須與程式設計人員、視覺設計人員、內容作者等,密切合作。

所以,資訊架構師的大部份產出(Deliverables)是溝通資訊,maps 和diagrams只是溝通工具而已,不可本末倒置。 因為資訊架構師要和網站設計團隊各成員(視覺美工、程式設計、內容作者、長官)溝通,所以傾聽(Listening)是必要的能力。


Falling in and out and in love with Information Architecture

UI vs. UX vs. IA vs. ID :4 Confusing Digital Design Terms Explained

  • UI design is how the elements on an application work together to ease users’ interaction
  • UX design is the satisfaction a user derives from using an application
  • IA (Information Architecture) is how the application is structured to ease finding information
  • ID (Interaction Design) is the reaction between an application and its users when they interact


TOP        
     
*** 想玩 IoTtalk 物聯網應用的點這看 IoTtalk 物聯網應用操作入門
Tensorflow Python API   AIoT 2019   AIoTㄒㄇ   AIoT_iii   AIoT   AIoT_清華台北  

好了, 休息一下 .. 來點輕鬆的 ..
    華佗和李時珍都說過 .. 健康很重要 .. 沒有健康想用功也沒精神 ..
    所以我幫大家整理了一些健康常識..
    請用 GOGLE.COM 搜尋 感冒 + 蔡神就在你身邊
    就會找到 感冒其實沒有藥 這網頁 :-)
    啥? GOGLE 寫錯了 !? ㄟ, 拜託, 我是蔡神ㄟ, 怎可能寫錯 !??
    阿那個聽我說:
        第一, 網址的網站部分 和 Email 名稱全部 都沒有大小寫之分 !
          注意網址在網站名稱結束 斜線 / 之後開始 是目錄或檔案名稱, 所以當然有大小寫的差別 !
        第二, Google 當初怕大家鍵盤有問題(或手指頭有問題:), 敲 O 可能多一個 O 或少一個 O,  
    所以乾脆把 gOgle.com 、 gOOgle.com 、 gOOOgle.com 三個網址都買了。
    不信你在網址列打 GOGLE.com 、 gOOgle.com 、 以及 gOOOgle.com 測試看看 !
    再說一次, Email 沒有大小寫,
    所以 tsaiwn@gmail.com 和 TSAIWN@Gmail.COM 是完全相同的;
    如果你 Email 含有 123 的 1 以及 LP 的 L, 千萬記得把 字母 l 打成 L 免得別人弄錯了 !
    看到沒, 上列我打 l 是小寫 L 看起來像大寫 I 也像數字 1 會讓人搞不清ㄟ !
    所以, Email 名稱應該避免用數字 1 啦 !
    還有, 如果字母 L 混在數字內就打大寫 L 免得被誤會成 1 2 3 的 1 喔。

           
休息..繼續.. 那個 Python 可以拿來練習寫其它不是網頁的程式嗎 ?
阿這不是廢話嗎 !? 當然可以拿來做任何事, 就先來練習久久乘法表好了..
對啦, 是 九九 啦 !
孔老夫子說過: 九九乘法表 是 練習 Loop control (迴圈控制) 最好的例子 !
* 總共要印出九列, 可以用 for i in range (1, 10): 表示要讓 i 從 1 做到 9 共九次
* 每列要印出九次, 每次印完顯然不可以換列--只要在 print( ) 內指定 end=""
  ==> 當然每印完一列九個數之後, 要換列(換行)這樣:
          print( ) # 括號裡面啥都不要寫即可
* 以下共有 12 個相關的小範例, 先看看並先想像一下答案, 然後 python3 檔案 測試
* 也可以試著照自己意思改並測試看有沒跟原先想的一樣, 不一樣就問 :-)
* 注意, Python 很注重縮格編排, 不要亂縮格, 不要亂空格 !
👉 REPL.IT REPL.IT REPL.IT ... 很重要所以說三次 !
**可到這https://REPL.it/languages/python3線上輸入 Python 程式碼測試 (可複製片段程式碼貼上測試)    

👉 在開始研究久久乘法表(九九乘法表)之前, 先來看看"防呆"的概念 ..      
* 忐忑 .. 這個呆 .. 那個呆 注意, 就是要防呆啦 !   
**這有"學姐的遊戲在REPL.IT"(不是柯P的學姐, 應該是和前面寫無聊小遊戲同班的:-) 這樣也能玩喔:-/
     ☠ 她這程式要你輸入數字選擇時如果你只按 Enter 會使程式當掉 (Crash) ! ☠
  ==> 該回答 數字 卻只按 ENTER 鍵會當掉 !
  *這份 https://repl.it/repls/LowScratchyArrays 我改了一點點做防呆 (故意按 Enter 不選答案看看)
    負責任的程式要有防呆機制(防止呆子亂輸入) -- Exception Handling (例外處理)
      ⇘ 注意看 Line 1742 到 Line 1748 這段程式碼 !   ⇙ 要學起來喔 !
     
***執行這 Python 程式猜猜顯示的藝術圖案是啥動物 ?
***隨時可以到這網站 https://REPL.IT 線上玩 Python
***關於 REPL.IT 介紹請點這   或   看 Youtube 影片介紹 REPL.IT

ℋ ℌ 👍 想要查符號的 Unicode (UTF-8)       👍 😂 🐞 ⌘ ♞ ❣ ©

Top  幾個英文字讀音
TOP        
       
好啦, 開始來研究九九乘法表的程式..
**可到這https://REPL.it/languages/python3線上輸入 Python 程式碼測試 (可複製片段程式碼貼上測試)
test38@hwsrv-307897:~$
test38@hwsrv-307897:~$ PS1="\u\$ "
test38$ alias ll='ls -l'
test38$ ll
total 56
drwxrwxr-x 2 test38 someguests 4096 Jan 22 00:16 ./
drwxrwxr-x 6 test38 someguests 4096 Jan 21 22:36 ../
-rw-rw-r-- 1 test38 someguests   37 Jan 22 00:04 991.py
-rw-rw-r-- 1 test38 someguests   56 Jan 22 00:06 992.py
-rw-rw-r-- 1 test38 someguests  248 Jan 22 00:08 995.py
-rw-rw-r-- 1 test38 someguests  127 Jan 22 00:10 996.py
-rw-rw-r-- 1 test38 someguests   98 Jan 22 00:11 997.py
-rw-rw-r-- 1 test38 someguests  148 Jan 21 23:09 998.py
-rw-rw-r-- 1 test38 someguests  101 Jan 21 22:47 999.py
-rw-rw-r-- 1 test38 someguests  117 Jan 21 22:59 99a.py
-rw-rw-r-- 1 test38 someguests  116 Jan 21 22:50 99b.py
-rw-rw-r-- 1 test38 someguests  177 Jan 21 23:01 99c.py
-rw-rw-r-- 1 test38 someguests  164 Jan 21 23:03 99d.py
-rw-rw-r-- 1 test38 someguests  106 Jan 21 23:08 99x.py
test38$ cat 991.py

for i in range(1, 10):
    print(i)
test38$ python3 991
python3: can't open file '991': [Errno 2] No such file or directory
test38$ python3 991.py
1
2
3
4
5
6
7
8
9
test38$ cat 992.py

for i in range(1, 10):
    print(i, end=" ")
print( );
test38$ python3 992.py
1 2 3 4 5 6 7 8 9
test38$ cat 993
cat: 993: No such file or directory
test38$ cat 995.py

i=2
for j in range(1, 10):
    print(j*i, end=" ")
print( );

i=3
for j in range(1, 10):
    print(j*i, end=" ")
print( );

i=4
for j in range(1, 10):
    print(j*i, end=" ")
print( );

i=5
for j in range(1, 10):
    print(j*i, end=" ")
print( );

test38$ python3 995.py
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
test38$
test38$ cat 996.py

for i in range(2, 7):    # 2, 3, 4, 5, 6   (Note not include 7)
  for j in range(1, 10):
    print(j*i, end=" ")
  print( );

test38$ python3 996.py
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
test38$
test38$ cat 997.py

for i in range(1, 10):    #   1..9
  for j in range(1, 10):
    print(j*i, end=" ")
  print( );

test38$ python3 997.py
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81
test38$

test38$ cat 998.py
for i in range(1, 10):
    for j in range(1, 10):
        if( i*j < 10): print(" ", end="")
        print(" {} ".format( i*j) , end="")
    print()
test38$ python3 998.py
  1   2   3   4   5   6   7   8   9
  2   4   6   8  10  12  14  16  18
  3   6   9  12  15  18  21  24  27
  4   8  12  16  20  24  28  32  36
  5  10  15  20  25  30  35  40  45
  6  12  18  24  30  36  42  48  54
  7  14  21  28  35  42  49  56  63
  8  16  24  32  40  48  56  64  72
  9  18  27  36  45  54  63  72  81
test38$
test38$ cat 999.py
for i in range(1, 10):
    for j in range(1, 10):
        print(" %2d" % (i*j), end=" ")
    print()
test38$ python3 999.py
  1   2   3   4   5   6   7   8   9
  2   4   6   8  10  12  14  16  18
  3   6   9  12  15  18  21  24  27
  4   8  12  16  20  24  28  32  36
  5  10  15  20  25  30  35  40  45
  6  12  18  24  30  36  42  48  54
  7  14  21  28  35  42  49  56  63
  8  16  24  32  40  48  56  64  72
  9  18  27  36  45  54  63  72  81
test38$

test38$ cat 99a.py
for i in range(1, 10):
    for j in range(1, i+1):
        print('{}x{}={}\t'.format(j, i, i*j), end='')
    print()
test38$ python3 99a.py
1x1=1
1x2=2   2x2=4
1x3=3   2x3=6   3x3=9
1x4=4   2x4=8   3x4=12  4x4=16
1x5=5   2x5=10  3x5=15  4x5=20  5x5=25
1x6=6   2x6=12  3x6=18  4x6=24  5x6=30  6x6=36
1x7=7   2x7=14  3x7=21  4x7=28  5x7=35  6x7=42  7x7=49
1x8=8   2x8=16  3x8=24  4x8=32  5x8=40  6x8=48  7x8=56  8x8=64
1x9=9   2x9=18  3x9=27  4x9=36  5x9=45  6x9=54  7x9=63  8x9=72  9x9=81
test38$ cat 99b.py
for i in range(1, 10):
    for j in range(i, 10):
        print('{}x{}={}\t'.format(j, i, i*j), end='')
    print()
test38$ python3 99b.py
1x1=1   2x1=2   3x1=3   4x1=4   5x1=5   6x1=6   7x1=7   8x1=8   9x1=9
2x2=4   3x2=6   4x2=8   5x2=10  6x2=12  7x2=14  8x2=16  9x2=18
3x3=9   4x3=12  5x3=15  6x3=18  7x3=21  8x3=24  9x3=27
4x4=16  5x4=20  6x4=24  7x4=28  8x4=32  9x4=36
5x5=25  6x5=30  7x5=35  8x5=40  9x5=45
6x6=36  7x6=42  8x6=48  9x6=54
7x7=49  8x7=56  9x7=63
8x8=64  9x8=72
9x9=81
test38$
test38$ cat 99c.py
for i in range(1, 10):
    for b in range(1, 10-i):
        print(end="        ");
    for j in range(1, i+1):
        print('{}x{}={}\t'.format(j, i, i*j), end='')
    print()
test38$ python3 99c.py
                                                                1x1=1
                                                        1x2=2   2x2=4
                                                1x3=3   2x3=6   3x3=9
                                        1x4=4   2x4=8   3x4=12  4x4=16
                                1x5=5   2x5=10  3x5=15  4x5=20  5x5=25
                        1x6=6   2x6=12  3x6=18  4x6=24  5x6=30  6x6=36
                1x7=7   2x7=14  3x7=21  4x7=28  5x7=35  6x7=42  7x7=49
        1x8=8   2x8=16  3x8=24  4x8=32  5x8=40  6x8=48  7x8=56  8x8=64
1x9=9   2x9=18  3x9=27  4x9=36  5x9=45  6x9=54  7x9=63  8x9=72  9x9=81
test38$

test38$ cat 99d.py
for i in range(1,10):
    for k in range(1,i):
        print (end="       ")
    for j in range(i,10):
        print("%d*%d=%2d" % (i,j,i*j),end=" ")
    print("")
test38$ python3 99d.py
1*1= 1 1*2= 2 1*3= 3 1*4= 4 1*5= 5 1*6= 6 1*7= 7 1*8= 8 1*9= 9
       2*2= 4 2*3= 6 2*4= 8 2*5=10 2*6=12 2*7=14 2*8=16 2*9=18
              3*3= 9 3*4=12 3*5=15 3*6=18 3*7=21 3*8=24 3*9=27
                     4*4=16 4*5=20 4*6=24 4*7=28 4*8=32 4*9=36
                            5*5=25 5*6=30 5*7=35 5*8=40 5*9=45
                                   6*6=36 6*7=42 6*8=48 6*9=54
                                          7*7=49 7*8=56 7*9=63
                                                 8*8=64 8*9=72
                                                        9*9=81
test38$ cat 99e
cat: 99e: No such file or directory
test38$ cat 99x.py
for i in range(1, 10):
	for j in range(1, 10):
        print(" {} ".format( i*j) , end="")
    print()
test38$ python3 99x.py
 1  2  3  4  5  6  7  8  9
 2  4  6  8  10  12  14  16  18
 3  6  9  12  15  18  21  24  27
 4  8  12  16  20  24  28  32  36
 5  10  15  20  25  30  35  40  45
 6  12  18  24  30  36  42  48  54
 7  14  21  28  35  42  49  56  63
 8  16  24  32  40  48  56  64  72
 9  18  27  36  45  54  63  72  81
test38$

test38$
test38$ cat 999.py
for i in range(1, 10):
    for j in range(1, 10):
        print(" %2d" % (i*j), end=" ")
    print()
test38$ python3 999.py
  1   2   3   4   5   6   7   8   9
  2   4   6   8  10  12  14  16  18
  3   6   9  12  15  18  21  24  27
  4   8  12  16  20  24  28  32  36
  5  10  15  20  25  30  35  40  45
  6  12  18  24  30  36  42  48  54
  7  14  21  28  35  42  49  56  63
  8  16  24  32  40  48  56  64  72
  9  18  27  36  45  54  63  72  81
test38$



test38$ cat 991a.py

for i in range(1, 10):
    print( "第 %d 列"  % i)
test38$ python3 991a.py
第 1 列
第 2 列
第 3 列
第 4 列
第 5 列
第 6 列
第 7 列
第 8 列
第 9 列
test38$

test38$ cat 991b.py 

for i in range(1, 10):
    print( "第 {} 列".format( i) )
test38$ python3 991b.py
第 1 列
第 2 列
第 3 列
第 4 列
第 5 列
第 6 列
第 7 列
第 8 列
第 9 列
test38$


test38$ cat padd.py # Use variables num1 and num2 to store input numbers num1 = input('Enter first number: ') num2 = input('Enter second number: ') # Add two numbers sum = float(num1) + float(num2) # Display the sum print('The sum of {0} and {1} is {2}'.format(num1, num2, sum)) print('Again, The sum of {} and {} is {}'.format(num1, num2, sum)) test38$ test38$ python3 padd.py Enter first number: 123 Enter second number: 456.38 The sum of 123 and 456.38 is 579.38 Again, The sum of 123 and 456.38 is 579.38 test38$ test38$
# Python 的 float 就是其它語言的 double, 準確度大約 16 位多一點 (54 * 0.3010) test38$ cat p.py #x=123456789012345.0 #x=0.2 ===> 0.2 + 0.8 = around 1.0 y=0.001 def dodo(x): ans = float(x) for i in range(0, 800): # 0.001 *800 = 0.8 ans += y return ans # 回傳答案 #please give me 0.1 ~ 12345 x = input("Give me x: "); print( ) print("Before Loop, x=", x) print(" After Loop, x=", dodo(x) ) # #please give me 1234567890135246.0 x = input("Give me x: "); print( ) print("Before Loop, x=", x) print(" After Loop, x=", dodo(x) ) test38$ test38$ python3 p.py Give me x: 100 Before Loop, x= 100 After Loop, x= 100.80000000000382 Give me x: 0.2 Before Loop, x= 0.2 After Loop, x= 1.0000000000000007 test38$ test38$ !py Give me x: 123456789 Before Loop, x= 123456789 After Loop, x= 123456789.80000162 Give me x: 1234567890 Before Loop, x= 1234567890 After Loop, x= 1234567890.799942 test38$ test38$ !py python3 p.py Give me x: 12345678901234.0 Before Loop, x= 12345678901234.0 After Loop, x= 12345678901235.562 Give me x: 123456789012345.0 Before Loop, x= 123456789012345.0 After Loop, x= 123456789012345.0 test38$ # 注意看上面.. Loop 前後答案相同 ! 這表示 加了 800 次也沒用 ! Why?
使用 while True: 不斷的做直到輸入是 -1 test38$ cat p2.py x=1234567890135246.0 #x=0.2 y=0.001 def dodo(x): ans = float(x) for i in range(0, 800): # 0.001 *800 = 0.8 ans += y return ans #please give me -1 to stop x = input("Give me x: "); while(True): if( x == "-1"): break; print("Before Loop, x=", x) print(" After Loop, x=", dodo(x) ) print() x = input("Give me x: "); # print("Bye bye !") test38$ python3 p2.py Give me x: 0 Before Loop, x= 0 After Loop, x= 0.8000000000000006 Give me x: 100 Before Loop, x= 100 After Loop, x= 100.80000000000382 Give me x: 100.2 Before Loop, x= 100.2 After Loop, x= 101.00000000000382 Give me x: 123456789012.1 Before Loop, x= 123456789012.1 After Loop, x= 123456789012.90567 Give me x: 123456789012345.0 Before Loop, x= 123456789012345.0 After Loop, x= 123456789012345.0 # 注意看上面.. Loop 前後答案相同 ! 這表示 加了 800 次也沒用 ! Why? Give me x: 12345678901234.0 Before Loop, x= 12345678901234.0 After Loop, x= 12345678901235.562 # 注意看上面.. 理論上應該只加入 0.8 ... 可是多 1.562 哪也安捏 ??? Give me x: 1234567890123.0 Before Loop, x= 1234567890123.0 After Loop, x= 1234567890123.7812 # 注意看上面.. 理論上應該只加入 0.8 ... 可是 這 0.7812 也不太夠 ??? Give me x: -1 Bye bye ! test38$

**可以到這網站 https://REPL.IT 線上輸入或貼入 Python 程式碼測試
  *關於 REPL.IT 介紹請點這     或   看 Youtube 影片介紹 REPL.IT

* 如何輸入兩個數 ?
x, y = input("Give me 2 numbers: ").split( )
    這時可輸入例如 12.345 6688
    但是, 若輸入 12.345, 6688 則會當掉 !
    ==> 還有, 注意, x 和 y 都是字串, 必要時可以用 float(x) 和 int(y) 轉換成你要的資料!
    但是, 萬一輸入的是錯誤資料, 轉換無法成功時程式也會當掉!
    ==> 所以, 最好用 try: ... except: ... 把轉換的句子夾起來做例外處理!!!

* 以下範例可幫你讀入三個數, 且不會被輸入搞當掉: (空白或逗號格開都可以!)
gg = input("Give me 3 numbers: ")
gg += ",-1,-1,-1"    # 萬一他都沒打字
gg = gg.replace(" ", ",")  # 空格改為逗號
gg = gg.split(",")  # 根據逗號拆開
gg = [x for x in gg if x != ""]   # 去除所有空字串
(x, y, z, *_) = gg   #  前三個放入 x, y, z
try:   # 必要時以下三個分開 try:...
   x = float(x)   # 假設你要實數
   y = float(y)   # 先這樣萬一輸入有小數點也沒關係 :-)
   if y == -1: y = -1
   else:  y = int(y+0.5)   # 假設這要整數, 即使輸入有小數, 也轉為整數, 四捨五入
   z = float(z)  # 假設這個要實數
except:
   print("input x y z something wrong!")
   if not type(x) is float: x = -1
   if not type(y) is int: y = -1
   if not type(z) is float: z = -1
if(x >= 0):
   print("x=", x)
if(y >= 0):
   print("y=", y)
if(z >= 0):
   print("z=", z)
## 注意, 我們這裡是假設 -1  代表沒輸入或輸入了不要的值!

   
 
TOP        
     
  
Python 程式碼的慣例   (Python Coding Style) 
      Python 程式檔案通稱腳本(Script), 考慮 Script 可能要被匯入(import),
一定做的事建議寫在一個主函數(函式)例如 main() (名稱可以任意),
然後在腳本的最後先如下檢查:
if __name__ == '__main__' :
如果成立 再執行該"主函數。
例如:     (注意縮格對齊)
def main():   # 並沒規定壹定要叫做 main( )
      ...
      ...
if __name__ == '__main__': # 如果是被 import 則這句不會成立; 那就不會執行以下句子
    main()

注意, 在 Python 中, pychecker, pydoc, 及 unit test 的 module 都應該能被 import。
為確保 module 被 import 時不會執行主程式,每一個 module 在執行主程式前都應該如上檢查 !!!
還有, 當一個 module 被 import 時,頂層(最外層)的所有程式碼都會被執行。
所以,在頂層不應該有呼叫函式(call function)、創建物件(create Object)、或執行不該在使用 pycheck 或 pydoc 時被執行的動作。
    還有, 建議程式碼中不要用 TAB, 不要用 TAB, 不要用 TAB (很重要所以說三次)!
因為那會和空格搞混 (看不出來啊!) !
阿就是說縮排請一律打空格啦, 雖然一般建議縮四格(很多編輯器會自動), 但我都只用3格或 2格:-)

        程式設計其實很簡單, 阿就是把電腦當作一個很厲害但很聽話的小孩子,
把要做的事鉅細靡遺的細節告訴他 ! 例如這句做完後要做哪句要給判斷規則,
這就叫做控制語句(Control statement),
常見的 Control statement 控制語句:
      * if ...else
    假如 (這條件成立): 做這些事; else: 否則做這些事 (注意 if 條件之後要冒號, else 右邊也要冒號 !
      * for Loopwhile Loop     ( while (肚仔還餓) : 吃吃吃; 喝喝喝 )
      * break (用在 Loop 中途離開; 包括 for Loop 和 while Loop ) 和 ..
      * continue (繼續 while Loop 或 for Loop 的下一回合, 但放棄目前這回合還沒做完的剩下 code)
      * pass (在規定一定要寫些句子之處, 如暫時不想寫, 就先寫 pass 讓編譯器不會抱怨!)


啥啦? 是很想學 Python 語言的語法(Syntax .. syntax.. python syntax) ?
      好啦, 加減先來講一些..
      其實, 所有電腦語言的語法都大同小異, 阿不過 Python 有點跟別人不太一樣:
      第一、 Python 寫法上很像英文的寫法
          但是, 不要隨便空白, 不要隨便空白! 尤其是每列的開始更不要隨便空白!!!
          ** 可以點這看 Python 程式碼風格指引     Python Style Guide   ==     PEP8 and PEP257
      第二、 Python 寧可要冒號 : (colon), 但 分號( ; semicolon) 就可以免了!

  // 其它語言(C/C++/Java)強調每句結束都要分號, 但當然偶有例外: (其它很多語言 // 是註解)
          * 當結束是右大括號 } 之時, 後面分號可以省去, 但是寫了也 OK
          * 但這例外又有例外, 就是如果這 } 是在描述資料(data)則分號又不可以省略, 例如:

            int x[ ] = { 12, 256, 5566, 3388, 999, 234, 38 }; // 這個分號不可以省略 !
          * 注意, 以上說的是"其它語言(C/C++/Java)", 不是在說 Python 喔 !
  # Python 每句結束的分號可以不必寫 ! 反而是, 很多狀況要用冒號 : (Python語言 # 是註解)
          * if 條件之後要寫 : 冒號
          * else 之後要寫 : 冒號, 以及 可搭配 0 個到很多個的 elif 條件後也是要寫 : 冒號
          * for 和 while 在條件之後 也都要寫冒號

                Python 不可以亂空白凹入(indent; 縮入), 其凹入是有意義的 !!!
                符合 if/elif/for/while等條件要做的事就凹入幾格就對了, 要凹入幾格沒規定,
                但在該條件下要做的每句要凹入一樣多, 除非(就說過總有例外):
                      (a)這列是前一列還沒寫完的, 這時前一列最後是反斜線 back slash \
                      (b)這列是"多列式字串", 就是用三個單引號(雙引號)開頭的, 直到下一次出現連續三個引號前是多列字串 !
                          這種多列式字串有些人以為是註解, 其實它是字串, 只是剛好可當作註解 :-)
          * def functionName(參數):
                  Python 隨時可以定義一個函數(function; 函式),
              包括正在寫函數內容時都可臨時寫個臨時函數..當然只能臨時用囉 !

              函數的身體(內容)就是在下一列開始凹入數格寫就對了, 愛寫幾列就可以幾列 !
              ==> 函數可以送回任何物件或任何值, 當然是用 return 物件 或 return 值
              ==> 函數的最後一句如果只是 return 可以忽略不寫(就是沒說要 "送回" 啥東東)
              ==> 函數裡面的變數如果有出現在 = 等號左邊則預設是局部(Local)變數, 除非你宣告它是 global
          * 以上就是所有能讓程式碼不是照寫的前後順序執行的語句,
            稱之為流程控制語句(Control statement), 或簡稱控制語句。

          * 這個 Python3 教學網站語法講得很完整 (對啦, 前面給過了)
          * 要看中文的, 可以 到這"菜鳥教程"有很多教學 (是老共的網站, 名詞是老共講法)
    * 遞迴(Recursive)函數(function; 函式)就是會直接或間接叫用自己的函數 !
          遞迴函數(Recursive function)很容易實作, 通常就是方法(演算法)想完就寫出來了, 很直覺!
例如, 如果不考慮負數, 則 N 階乘的函數可這樣寫:
def fact(n):
    if n == 0: return 1   #   0 階乘 答案 1
    return n * fact(n-1)   #  n 階乘 就是 n 乘以  (n-1)階乘         
# 測試以下這會算 N 階乘的完整程式: (Recursive 遞迴函數)
def fact(n):    # 定義 n 階乘 函數 (函式)
    if(n==0): return 1  #   0 階乘 答案 1
    if(n<0): return -fact(-n)   #如果 n 是負的, 那答案就是 - (-n 階乘)
    return n* fact(n-1)   #  n 階乘 就是 n 乘以  (n-1)階乘     

while True:
    n = input("Give me n (3388 to quit): ")
    n = int(n)  # 亂輸入會當掉
    if n==3388: break    # 故意規定 3388 這特殊值表示要結束; break 會離開 Loop
    print(n, " != ", fact(n) )   # 印出 n 階乘 的答案

print("Bye!")    #  如果用 Interactive 那這列就不要 
又例如, 求兩數 GCD (最大公約數) 的輾轉相除可以寫成以下遞迴函數:
def gcd(m, n):
    if n == 0: return m   #   若 n 是 0, 答案就是 m 啦
    return gcd(n, m % n )   # 否則答案就是 gcd(n , m 除以 n 的餘數) 阿就輾轉相除咩
  * 注意! 注意! 注意! 遞迴(Recursive)演算法雖好寫, 但其實很慢很慢很慢 !!!
    不相信可以用遞迴法算費伯納西(Fibonacci)第 66 個月有幾對兔子?
      (Hint: 要算很多天喔 ! )
    費氏數列:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, ...
  神奇的黃金分割比:
      233/377 = 377/610 = 610/987 = 987/1597 = 0.618
      377/233 = 610/377 = 987/610 = 1597/987 = 1.618
      377/144 = 610/233 = 987/377 = 1597/610 = 2.618
      1.618 / 2.618 = 0.618
      2.618 / 1.618 = 1.618
# 測試以下這會算 第 n 個月幾對兔子的完整程式: (也是 Recursive 遞迴函數)
def fib(n):    # 定義 第 n 個月幾對兔子如何算
    if 0 >= n : return 0  #   以前沒兔子; fib(0) 也規定是 0
    if n==1 : return 1    #   第一個月, fib(1), 有一對兔子
    return fib(n-1)+fib(n-2)   # 每個月兔子幾對都是等於前兩個月兔子幾對的相加

import time
while True:
    n = input("Give me n (3388 to quit): ")
    n = int(n)  # 亂輸入會當掉
    if n==3388: break         # 故意規定 3388 這特殊值表示要結束; break 會離開 Loop
    timeStart = time.time( )
    ans = fib(n)
    timeEnd = time.time( )    ## 因為 print 也要花不少時間, 所以先算好再 print 
    print("第 ", n, " 個月有 ", ans , " 對的兔子。", end="") 
    print("== Elasp time = {:.7f} sec.".format(timeEnd - timeStart) )

print("Bye! Bye!!")    #  如果用 Interactive 那這列就不要 
# 補充說明: Leonardo Fibonacci 在公元1202年寫的書中提出了一個問題:
#     假設兔子永遠不死, 假設 baby 兔子要一個月才長為成兔; 假設每對成兔過一個月會生出一對 Baby 兔子。
#     第 0 個月沒有兔子, 第一個月養了一對 Baby 兔子, 請計算第 n 個月會有幾對兔子?
#  變化題:   (a)改變長大所需月數, (b)改變懷孕所需月數

    ==> 試這 Repetition (Loop) 版本看看有多快 !!!
# 測試以下這會算 第 n 個月幾對兔子的完整程式: (改用 Loop 的函數)
## Fibonacci series, repetition version; by tsaiwn@cs.nctu.edu.tw
import numpy    # 這裡面有 array 可以用 (其實用 list 即可)
def fib(n):     ## 注意 int64 只能算到 fib(92) 
    if( 0 > n): return 0
    rab = numpy.arange(123, dtype='int64')   # array 123 個元素 (只是故意讓你知道有 numpy 的 array)
    ## rab = [0] * 123    ## 其實用這 List 可以整數無窮大; 愛算到 n 多少都可以
    rab[0] = 0
    rab[1] = 1
    for i in range(2, n+1, 1):     ## 從 fib(2) 算到 fib(n) 
        rab[i] = rab[i-1] + rab[i-2]
    return rab[n]   # 幾對 rabbits on n-th month

import time
while True:
    n = input("Give me n (3388 to quit): ")
    if n == "q" or n=="quit": break
    try:
        n = int(n)   ##  用了 try: ... except: ..  之後, 就不怕亂輸入了 :-) 
    except:
        continue
    if n==3388 or n== -1: break     # 故意規定 3388 這特殊值表示要結束; break 會離開 Loop
    timeStart = time.time( )
    ans = fib(n)
    timeEnd = time.time( )
    print("第 ", n, " 個月有 ", ans , " 對的兔子。", end="") 
    print("== Elasp time = {:.7f} sec.".format(timeEnd - timeStart) )

print("Bye! Bye!!")    #  如果用 Interactive 那這列就不要 
    ===============================================
** 函數(function; 函式)也可以送回很多值喔 !
      (其實是包裝成 tuple 元素組)
# 測試以下這會送回三個值的完整程式:
def haha(n):    # 接受一個參數 n
    return  n*n, n**3, 5566   #  回傳 ( n 平方, n 立方, 5566 )   

while True:
    n = input("Give me n (3388 to quit): ")
    n = int(n)  # 亂輸入會當掉
    if n==3388: break         # 故意規定 3388 這特殊值表示要結束; break 會離開 Loop
    print(" n = ", n, ", haha(n) 得到 ", haha(n) )
    print(" type of haha(n) 是 ", type(haha(n)) )
    x, y, *_ = haha(n)    # 我只要答案的前兩個 ; 但如只回傳一個值會當掉!
    print("x 得到 ", x, ", y = ", y)
    gg, *_ = haha(n)    # 只要第一個, 其它不 care
    print("gg = ", gg)
    a, b, c, *_ = haha(n)    # 萬一 haha(n) 回傳四個值也 OK; 只要至少三個值都可以
    print("c = ", c)     #  c 應該是 5566;  因在 haha( ) 內的第三個回傳值是 5566

** tuple 到底念 "踏 剖" 還是念 "踢 U 剖" ?
      都有人念ㄟ.. Google 和劍橋字典不同!     也點這看看

** 函數(function; 函式)也可以送回很多值喔 !

** 注意! 注意! 注意!  
      Python 沒有 ++ 和 -- 喔! 雖然寫了不會報錯, 但其意義和 C/C++/Java 不同喔!!!

    ** 現在先 來看看 以前我在 Java 語言(和 C/C++) 講義內講解 while Loop + break + continue 的圖
            (被偷去放網路分享網站)

         
      *** Python 的 for Loop 語法和其它語言不太相同,
              其它(C/C++/Java)的語法如下(順便看看囉):
              (while Loop 和 for Loop 其實是互通的)

                      for( 初始句子; 檢查條件的句子; 做完每一回合後要做的句子) Loop_Body_迴圈本體的句子;    
         
            其它(C/C++/Java)的 for Loop 範例: (Java 要用 System.out.printf( ) 且不太相同)
            假設要做 : 讓 i 從 1 做到 10 每次加 2 : 1, 3, 5, 7, 9 (離開時是 i==11)
#include <stdio.h>
int main( ) {
    int i;   //  C 語言不能等到在 for( 內宣告  
    for(i=1; i < 10; i+=2) {
       printf("i=%d,  ", i);
       printf("i*i=%d, ", i*i};    //  這裡故意有打錯, 找一下喔 !
       printf("i*i*i=%d\n", i*i*i);
    }
    printf("Now i=%d\n", i);   // 這時 i 是 11 
    printf("===bye===\n");
    return 0;
} // end of main
//  只故意打錯一個字, 改掉後所有的錯誤信息就不見了啦 !!!
      ** 要驗證上述 C 程式碼, 可以點這到 jdoodle 這 C++/C 線上網站 測試
         * C++ 就是比 C 好用一些的 C + class 類別概念, 支援"物件導向"程式設計概念
           ** 物件導向(Object Oriented; 點這跳到後面看物件導向概念) 老共翻譯為 "面向物件", 哈哈, 我還 "面向牆壁ㄟ" -- 只是覺得很好笑 :-)

      *** Java 語言沒有獨立的 printf( ) 函數, 它附屬在 System 這類別內,
                  所以 System.out 有類似函數可用; System.out 就是系統輸出裝置, 意思就是螢幕!

        ** Java 語言除了 System.out.printf( ); 還有 System.out.print( ); 和 System.out.println;
      *** 上面那 C 程式在 Python 要這樣寫:
for i in range(1, 10, 2):
   print("i=", i, end=",  ")   # 這句故意沒用格式化
   print("i*i=%d" % (i*i), end=", ")    #    (i*i) 一定要括號夾住 !
   print("i*i*i=%d\n" % (i*i*i), end="");

print("Now i=%d"  % i);    # Python 結尾有沒有 ; 分號都可以; 這時 i 是 9 
print("===bye===");
      ** 其實剛剛那網站也可以驗證 Python 喔, 當然要先到該網頁上一層去改選 Python 語言 !
      *** Python 的變數(Variable)不需要宣告, 且會自動轉型(type)
      *** Python 不論用不用格式一律用 print( ) 且預設會自動換列(new line, 換行)
            若不想換列, 就在最後一個參數指定 end="結尾字串"
            *注意上例 for i ... 下方第一句 print( ) 我故意沒用排版格式 !
            * 其實 Python 另外有 "字串{}字串字串{} 等等".format(變數常數或字串)
      *** Python 不可以亂空白凹入(indent; 縮入), 其凹入是有意義的 !!!
            以上面例子來說, 在 for i in ... 那句下方有三列凹入的就是其 Loop Body
            不過到底該凹入幾格並沒有規定, 只要對齊即可, 忽然凹兩格又忽然凹入三格就不可以喔 !  
            還有還有, 每句結尾要不要寫分號 ; 都可以, 看你心情囉 :-)
  Python Variable and Data Type (變數與資料型別)  
了解控制語句 (Control Statement)後, 你還需要知道如何表示和使用資料(Data),
阿就是整數(int)、實數(float)、布林(bool)、字串(str)、串列(List)... 等等, 電腦裡面都是一大堆 0 和 1, 要如何看待完全由程式設計者決定; 雖然 Python 變數不必宣告, 也會自動轉型, 但是運算時還是有一些規定! 可以先大略看看:(提醒 Python 的 float 是其它語言的 double 兩倍準實數)

* 關於 Python 內建型別: 簡單的值 (Python Built-In Types: Simple Values)
    ==> 看這篇也很好, 除了 Python 內建型別; 還有內建函數(Built-in functions)
        int, float, complex, bool, str, NoneType
    注意, 在 Python2 的 5/2 答案是 2 (這與 C/C++/Java 相同)
        但 Python3 的 5/2 答案是 2.5     ( 5//2 則答案是 2 )

    **Python Scalar Types** (純量型別;簡單型別)
Type Example Description
int x = 1 integers (i.e., whole numbers)
float x = 1.0 floating-point numbers (i.e., real numbers)
complex x = 1 + 2j Complex numbers (i.e., numbers with real and imaginary part)
bool x = True Boolean: True/False values
str x = 'abc' String: characters or text
NoneType x = None Special object indicating nulls

* 資料型別 https://www.programiz.com/python-programming/variables-datatypes

We can use the type() function to know which class a variable or a value belongs to and the isinstance() function to check if an object belongs to a particular class.

    ** Python3 的整數(int) 無上限, Python2 的整數最大是 9223372036854775807
test38$
test38$ python3
Python 3.6.5 (default, Aug 26 2018, 13:30:20)
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> gg=123
>>> type(gg)
<class 'int'>
>>> gg += 0.0
>>> type(gg)
<class 'float'>
>>> gg += "哈哈"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +=: 'float' and 'str'
>>> gg = "哈 " *7
>>> gg = "嘿嘿嘿 " + gg
>>> type(gg)
<class 'str'>
>>> print(gg)
嘿嘿嘿 哈 哈 哈 哈 哈 哈 哈
>>> gg.isinstance(str)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'isinstance'
>>> isinstance(gg, int)
False
>>> isinstance(gg, str)
True
>>> sys.maxsize
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'sys' is not defined
>>> import sys
>>> sys.maxsize
9223372036854775807
>>> x = sys.maxsize
>>> x += 2
>>> print(x)
9223372036854775809
>>> type(x)
<class 'int'>
>>> exit()
test38$ 

* 數值 與 數學運算:
        https://www.programiz.com/python-programming/numbers
* 關於 Python 的運算符號(Operators)
      數學、比較關係、邏輯(and/or/not)、Bitwise(各bit運算)、其它
      數學: +   -   *   /   % 取餘數   // Python3 新的整數除法    ** 次方 (從 Fortran 學來的)
  ==> 注意, 注意, 注意, Python 沒有 ++ 和 -- 喔 !
          但是可以用 += 和 -= 這兩個加入和減去運算。

* 關於 Python 的內建函數(Built-in funtions)
數學 Math 如 abs( )、max( ) 等;型別轉換 Type Conversion 如 int( )、float( ) 等;
還有 Iterables and Iterators如 len( )、slice( )、zip( )等;
  Composite Data Type 如 list()、tuple( )、dict( )等;
和 Classes, Attributes, and Inheritance 如 isinstance()、hasattr()、super()等;
以及 Input/Output、Variables, References, and Scope、其他 Miscellaneous 等等等...
* 這 W3schools.com 的文件比較漂亮:
      https://www.w3schools.com/python/python_variables.asp
* 或看官方文件(比較醜):
      https://docs.python.org/3/library/datatypes.html

* Python 的 陣列(Array) 和 C/C++ 的陣列不太一樣, 其實 Python 並沒有提供 native Array;
    雖然 Python 的 List 可以當作陣列(Array)使用, 但其實不太一樣;
    簡單說, List 的每個元素可以不同的 type, 但是,
    ==> 理論上 Array 每個元素 type 應該相同,
          這樣每個元素佔用同樣大小的記憶體, 存取與運算都比較快。
    至少有兩個程式庫提供了 array, 一個是 Python 的 array 模組, 請參考這:

      https://docs.python.org/3/library/array.html
  以及這教學文件:
      https://www.programiz.com/python-programming/array#list-arrays
    另一個很多人用的是 numpy 套件(1995名叫 numeric, 2006年改名 numpy), 請參考以下這篇:
      https://numpy.org/doc/stable/
  以及這教學文件:
      從零開始學資料科學:Numpy 基礎入門
  還有這教學文件:
      Python資料分析(三)NumPy

** 👉 Python.array versus numpy.array

* Python 的 Tuple 也很好用, 注意 Tuple 和 List 略有不同, 請看:
      https://www.programiz.com/python-programming/list-vs-tuples
      簡單說, 小括號 ( ) 夾起來叫 tuple;(元素組) ; 可用 tuple( list 物件 ) 把 list 轉為 tuple;
      中括號 [ ] 夾起來叫 list (串列); 可以用 list( tuple 物件 ) 把 tupple 轉為 list;
      tupple 和 list 兩者用起來都像 array;
      Tuple 的每個元素不可更改, 要改則須整個 tupple 一起改!; 例如:
          aa = [11, 22, 345, 55, 888] # list
          bb = (11, 22, 345, 55, 888) # tuple
          bb[2] = 3388 # 錯誤 !
          aa[2] = 3388 # 正確, 可以喔 ! 因為 aa 是 list
      但是以下正確:
          bb = (bb[0], bb[1], 3388, bb[3], bb[4])
      雖然, 這樣看起來效果就是 bb[2] 換掉了,
      但此時的 bb 這 tuple 已經與以前的 bb 使用不同的位置 (記憶體)!!
 
👉 👉 試試這更厲害的: (用到 zip( ) 函數) (兩個串列各對應元素相加啦 ! )
          cc = [ a+b for a, b in zip(aa, bb)]
## #方便大家複製去測試:
aa = [11, 22, 345, 55, 888] # list
bb = (11, 22, 345, 55, 888) # tuple
aa[1] = 33
aa[2] = 13  
cc = [ a+b for a, b in zip(aa, bb)]  # 各元素相加 
print("cc is a ", type(cc));
print("aa = ", aa)
print("bb = ", bb)
print("cc = ", cc)
### 開 CMD 窗 打 python 啟動 python 即可貼入測試; 結束打 quit( ) 或 exit( )

👉 👉 zip( ) 是 Python 的一個函數, 它是一種叫 "zip" 的類別: 一堆的 tuple 之物件
## #方便大家複製去測試:
aa = [11, 22, 33, 44, 55]
bb = (100, 200, 300, 356, 500)
kk = zip(aa, bb)
print("type of kk is ", type(kk) )    # "zip" 物件
print("list ( kk ) === ", list(kk) )  # 可用 list( 該物件 ) 取出; 注意取出後內部就清空了:
print("again, list ( kk ) === ", list(kk) )   # 注意 kk 變 空的喔 ! 
   
*Python 有個叫 map( ) 的函數很好用, 但注意跟 Arduino 的 map( ) 完全不同喔 !
## #** 請注意要套用函數的每個項目須確保套用函數不會當掉 !
gg = ["111", "22", "3388"]
print("gg = ", gg)
yy= map(int, gg)
yy = list(yy)     # Python 2 則必必這樣
print("yy is a ", type(yy))
print("  yy = ", yy)

def add2(x, y):
   return x + y     # 其實, 這種只一列的函數適合寫成 lambda function

aa = [10* x for x in range(1, 10)]   ## 10, 20, .. 90
bb = [ x for x in range(0, 10) if x != 0]   ## 1, 2, 3, .. 9
cc = map(add2, aa, bb)
cc = list(cc)  # 轉為 list
print("cc is a ", type(cc))
print("  cc = ", cc)

ff = map(lambda x, y: x+y, aa, bb)   # 使用 lambda 無名函數  
ff = list(ff)  # 轉為 list ; Python 2 則不必
print("ff is a ", type(ff))
print("  ff = ", ff)
print("ff 應該和 cc 相同..")
print("  is ff == cc ? ", ff == cc)


haha = [add2(a, b) for a, b in zip(aa, bb)]   # haha 已經是 list
print("haha 應該和 cc 相同..")
print("  是嗎? is cc== haha ? ", cc == haha)
print("  haha = ", haha)

a=[1, 2, 3, 5]    # 故意多一個 5, 在做 map( ) 會被忽略掉 !
b=[4, 5, 6]
c=[100, 200, 300]
hehehe = map(lambda x, y, z: x+y+z, a, b, c)    # 使用 lambda 無名函數  
hehehe = list(hehehe)
print("hehehe = ", hehehe)  # [105, 207, 309]

tmd = a + b + c     #  串接起來
print("length of tmd =", len(tmd))
print(" tmd = ", tmd)
xyz = [ tmd[x] for x in range( len(tmd) ) if x%2 == 1 ]  # 取奇數項; 注意第 0 項開始
print("xyz = ", xyz)

     
👉 👉 *Python 有個叫 Generator 的可以讓我們寫出多個入口(依序)的函數 !
## #** 請注意若不處理可能叫太超過的 next(gg) 會當掉 !
def myFun():
    n = 1
    print('This is printed first')
    print("第一階段完成囉")
    # Generator function contains yield statements
    yield n   #  類似 return n   但會記住下次從下一列進入 ; 用 next( ??)
#
    n += 200
    print('This is printed second 第二個入口')
    print("當然可以做很多事再 yield 啦!")
    yield n
#
    n = 301
    print('This is printed third 第三個入口')
    print("每次都可以做很多事再 yield 啦!")
    yield n
#
    n += 100
    print('This is fourth printting 第四個入口')
    print("注意這次 n 該是 401 , 右做很多事再 yield 啦!")
    yield n
#
    n += 155   # 沒規定 n 要如何變
    print('This is final, fifth printting  第五個入口')
    print("注意再次 next( ) 叫我可會當掉喔 !")
    yield n + 3388000    #  故意 3388556 

gg=myFun( )     # gg 得到 1
print("will call 2nd")   
y=next(gg)     ## y 得到 201
print("y = ", y)
while True:
   try:   
     zz = next(gg)     ## 301, 401, 3388556
     print("zz = ", zz)
   except:
     print("! try to call myFun( ) but ALL Done !")
     break;   #  別忘了要 break 喔 .. 離開 while

print("here after while Loop ...")




Python 的 List 串列並不是使用資料結構中的 Linked List 實作(implement) !
  👉 基於效率的問題, Python 使用可變動長度的 array 實作 list (array of pointers)


* Python 還有個很好用的 字典(Dictionary), 可以看這:
      https://www.programiz.com/python-programming/dictionary
* 注意 Dictionary 字典和 JSON 不同喔, JSON 是特殊字串表示的資料格式,
    在 Python 可以使用 JSON 程式庫(Library), 請參考:
      https://developer.rhino3d.com/guides/rhinopython/python-xml-json/

👉 👉 很厲害的 Landa 函數
      (a Landa function is a small anonymous function. 一個簡短的無名式函數)
## #方便大家複製去測試:
def myfunc(n): return lambda a : a * n     # a Lambda function

mydoubler = myfunc(2)
mytripler = myfunc(3)
print("double of 6 =", mydoubler(6))
print("triple of 6 =", mytripler(6))
  
    啥? 這樣很無聊? 看看以下這範例:
## #注意看 filter( ) 內的 lambda 函數 !
x = [ 3*i for i in range(10) if i%2 == 1]
y = filter( lambda n: not (n % 5 == 0), x)  # 濾掉可被 5 除盡的
print("  type of y = ", type(y))
print("y = ", y)
y = list(y)
print("x = ", x)    # [3, 9, 15, 21, 27]
print("y = ", y)    # [3, 9, 21, 27]       # 15 被過濾掉了 

def wanted(n):
   return not n%5 == 0

kk = [3*i for i in range(12) ]
mm = filter(wanted, kk)    # wnated 只有短短的一列就適合寫成 lambda function
print("kk = ", kk)  # [0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33]
mm = list(mm)
print("mm = ", mm)  # [3, 6, 9, 12, 18, 21, 24, 27, 33]
  
👉 👉 函數也可以寫成能夠接受不限數量的參數(parameter) !
## #注意以下 fff(*gg) 是用一個星號;
##### 另外 ggg(*gg, **yy) 的 **yy 是兩個星號 !
def fff(*gg):
  print("is gg a None:", gg == None)
  print("type of gg is: ", type(gg))
  print("You gave me: ", gg)

fff(1,2,3)
fff(1, 2)
fff(1)
fff( )
fff([1, 2, 3])

def ggg(*gg, **yy):  # 注意 yy is a dict of{key=val, ...}
   print("gg is ", type(gg))
   print("  gg = ", gg)
   print("yy is ", type(yy))   # should be a dict (dictionary)   
   print("  yy = ", yy)

ggg(1, 2, 3)
ggg(3, 2, 1, aa=123, name="ChangJM", tmd="他媽的", haha=543)

 
* global 變數是糖衣也是毒藥!
    一個好的函數(function; 函式)應該儘量不要使用 global 變數!
    尤其是, 如果函數是要給團隊中其他成員使用的更該如此!
    ==> 阿可是, global 很好用啊, 可以省去傳來傳去, ...
    對啦! 所以說是糖衣啊, 但是,
      使用 global 一不小心阿就讓你找好酒 .. 阿不是.. 是 "好久"都找不到哪裡錯!!!
    大約有一半的錯都是因為用了 global 但卻忘了宣告 global (或打錯字) 引起的!!!

* Python 的 global 其實不是那麼 global (全域) !
      蝦秘啦!?
      在函數內的變數, 若有出現在 = 等號左邊, 原則上是 Local (局部)變數;
      但有時你希望該句其實是要改變函數外的變數, 表示該變數是全域變數(global);
      則這時必須在函數內宣告它是 global;
      可是.. 可是, 這所謂的 global 其實比較像 C/C++ 的 static 變數!
      因為, Python 的 global 只限於同一個模組(module) (就是同一個檔案內啦!)
      ==> 在 C/C++ 如果在函數外的變數左邊加上 static 意思是 "global in this file ONLY"!
          在 C/C++ 如在函數內的變數左邊加上 static 意思是 "Local" 但離開函數會保留,
          下次進入函數可以繼續使用, 也就是設定初值只會做一次,
          以 Compiler 觀點就是它不是使用 Stack 堆疊記憶體啦!


👉 Python module(模組, 一個檔案稱一個模組)與 package (套件)的概念..
      關於 Python 的 module 與 import 一定要看看

** 關於 Python 的非同部(Async)處理 (unblock call) ... (難度高)
** 關於 Python 叫用 C 函數, 以及從 C 調用 Python 函數(難度高)    
以上關於 Python 語言的語法(Syntax .. syntax.. python syntax) .. 還沒完喔...

*** 夭壽喔 .. 怎這麼多東東!?
  A: 阿就跟你說先不要管文法你不信 !? 用到了再問 GOGLE 大神就好了 :-)
    好啦, 輕鬆一下, 看看如何用 python 的烏龜繪圖 . . .        
*** 用 Python 學 Turtle Graphic 烏龜繪圖好好玩

          ★ Turtle programming in Python   Documentations
    Fractals and Recursion in Python
    Snowflakes Fractal using Python
    A simple Fractal Tree using recursion in Python
    [Python Beginner][DIY] Make Fractal Trees
    Python Fractals     What are Fractals?(Wiki)
    Python Turtle Spirograph     Creating fractals with Python

# Turtle Graphics, 先試這畫一個方型 -- by tsaiwn@cs.nctu.edu.tw
length=150
import turtle             
p = turtle.Turtle()
p.penup( ); p.goto(-length/2, length/2) ;  
p.down( ); p.width(5)   #  p.pendown( )
for i in (1, 2, 33, 88):     ## 做四次, 故意 ! 但 i 沒用到 :-) 
   p.forward(length)           
   p.right(90) 
p.ht( )  

# Turtle Graphics, 再試這看看畫個星 -- by tsaiwn@cs.nctu.edu.tw
length=150
import turtle             
p = turtle.Turtle()
p.back(length/2)      
for i in range(5):
   p.forward(length)           
   p.right(144) 
p.ht( )    

# Turtle Graphics, 然後再試試這看看 -- by tsaiwn@cs.nctu.edu.tw
import turtle             
turtle.Screen().bgcolor("black")
turtle.pensize(2); turtle.speed(0)
for i in range(21):
   turtle.color("#55ff66");
   turtle.circle(5*i)
   turtle.color("cyan");
   turtle.circle(-5*i)
   turtle.left(i)

# Turtle Graphics, 再看看這畫啥碗糕 -- by tsaiwn@cs.nctu.edu.tw
from turtle import *
bgcolor("black"); color("black")
fillcolor("yellow"); st( )
begin_fill(); circle(100); end_fill()
up( ); goto(50,100); down( )
circle(10); pensize(5), circle(6); pensize(1)
up( ); circle(18, 100); down( ); circle(18, 160)
up( ); goto(-50,100); down( ); setheading(0)
circle(10); pensize(5), circle(6); pensize(1)
up( ); circle(18, 100); down( ); circle(18, 160)
up( ); goto(0,50); down( ); setheading(0)
pensize(3); color("deep pink")
circle(100,30)
up( ); goto(0,50); down( )
circle(0,-30)
circle(100,-30)
color("black")
up(); goto(0,80); setheading(90); st( )  # as nose :-)
           
遞迴函數 (Recursive function) 就是會直接或間接調用自己的函數(函式)
    以下是用 Recursive 方法畫出一顆樹 (tree) -- 每個人(每個函數) 只畫一條線
#turtle Graphics;  遞迴畫 Tree, 每次"減"短樹枝 -- by tsaiwn@cs.nctu.edu.tw
## 參考  https://bit.ly/2YUN578 以及 這 Introduction: Visualizing Recursion

angle, length = (25, 100)
minLen = 2
import turtle, random 
def tree(p, branchLen, angle): 
  if branchLen > minLen:   
    p.forward(branchLen)
    p.left(angle)  
    gg = 3 + random.randrange(25)    ## [3 .. 27]
    yy = 3 + random.randrange(25)    ## 讓它每次畫不太一樣
    tree(p, branchLen - gg, angle)  ## 畫左邊的樹
    p.right(angle * 2)    
    tree(p, branchLen - yy, angle)    ## 畫右邊的樹
    p.left(angle)
    p.backward(branchLen)  # 退回剛進入function時原處  
pen = turtle.Turtle(); pen.left(90)
pen.up( ); pen.backward(228); pen.down( )
pen.speed(0); pen.color("green")
tree(pen, length, angle)
另一種寫法, 每次縮短樹枝一個比例 (ratio)。這版故意左右對稱!
# Turtle Graphics;  Tree using 遞迴 Recursion -- by tsaiwn@cs.nctu.edu.tw 
angle, minLen = (35, 8)    #  角度, 最短樹枝
ratio = 2.0/3    # 每次縮短比例, 也可每次亂數變化一些
def makeTree(length):
    pensize(1)
    if length > 67: pensize(2)
    if length > 100: pensize(3)
    forward(length)
    if length >= minLen:   
        x, y = pos( )   # 記住 現在的 (x, y)
        hd = heading()  #  .. 以及 direction   
        left(angle)   
        makeTree(length*ratio)    # 畫出左邊的樹  
        penup( ); goto(x, y); down( )      # 回復到剛剛的 (x, y) ..
        setheading(hd)    #  .. 和 direction   
        right(angle)  
        makeTree(length*ratio)    # 畫出右邊的樹 
    
from turtle import *
Screen( ).bgcolor("black")
ht( )  ## hideturtle()
goto(0, -228); setheading(90)  # UP
color("green")
speed(0); st( )  
makeTree(200)  
penup( ); goto(0, -228)
setheading(90);

    以下這版 使用 .clone( ) 複製, 這樣只要不 .hideturtle( ) 就可留下 turtle HEAD 當葉子。
# Turtle Graphics;  Tree using 遞迴 Recursion -- by tsaiwn@cs.nctu.edu.tw
angle, length, minLen = (60, 200, 15)    # 角度, 初始樹枝長度, 最短樹枝長
ratio = 2.0/3   
def tree(branch, L, a, f):
    if minLen > L: return   # L 太短就不要畫了
    branch.forward(L)    
    br2 = branch.clone( )  # copy  目前 "筆尖" 資訊  成另一支筆 br2
    branch.left(a);    # 原先的 branch 往左旋轉, .. 然後,,  
    tree(branch, L*f, a, f )   ## 調用自己(tree)長出左邊的樹 
    br2.right(a);  tree(br2, L*f, a, f )  ## 利用 br2 長出右邊的樹 
import turtle, time
pen= turtle.Turtle( ); 
pen.left(90)  # 這樣箭頭往上, 等下 forward 可以往上畫畫
pen.backward(228)  #  Y軸退後 228;到底下
timeStart = time.time( )  
tree(pen, length, angle, ratio)  
print("Elasp time = {:.8f} sec.".format( time.time() - timeStart) )
print("bye!")

#turtle Graphics;  遞迴畫 Tree - 稍微改一點點 -- by tsaiwn@cs.nctu.edu.tw
length, angle = (200, 60)
ratio = 2.0/3   
import turtle, random, time  
def tree(branch, L, a, f):
    if 15 > L: return   # L 太短就不要畫了
    branch.forward(L)    
    gg = a+ 5 - random.randrange(11)   # a+ [-5, 5]
    yy = a+ 5 - random.randrange(11)   # a+ [-5, 5]   
    br2 = branch.clone( )  # copy  目前 "筆" 資訊
    branch.left(gg);    # 往左旋轉, .. 然後,,
    tree(branch, L*f, gg, f )   ## 調用自己(tree)長出左邊的樹
    br2.right(yy);
    tree(br2, L*f, yy, f )  ## 利用 br2 長出右邊的樹

pen= turtle.Turtle( ); pen.speed(0)  #  全速畫
pen.left(90)  # 這樣箭頭往上
pen.backward(228)  #  Y軸退後 228;到底下
timeStart = time.time( )
tree(pen, length, angle, ratio * (0.9+ random.random( )/10.0 ) )
print("Elasp time = {:.8f} sec.".format( time.time() - timeStart) )
print("bye!")

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#turtle Graphics;  遞迴畫 Tree - 亂數亂數亂數! -- by tsaiwn@cs.nctu.edu.tw
length, angle = (200, 60)
ratio = 2.0/3   
import turtle, random, time  
def tree(branch, L, a, f): 
    if random.randrange(3, 20) > L: return   # L 太短就不要畫了  
    branch.forward(L)    
    gg = a+ 8 - random.randrange(17)   # a+ [-8, 8]
    yy = a+ 8 - random.randrange(17)   # a+ [-8, 8]   
    br2 = branch.clone( )  # copy  目前 "筆" 資訊
    branch.left(gg);    # 往左旋轉, .. 然後,,
    tree(branch, L*f, gg, f )   ## 調用自己(tree)長出左邊的樹
    br2.right(yy);
    tree(br2, L*f, yy, f )  ## 利用 br2 長出右邊的樹
pen= turtle.Turtle( ); 
pen.color("#33ff55")   
while True:
    pen.speed(0)  #  全速畫
    turtle.Screen( ).bgcolor("black")
    pen.left(90)  # 這樣箭頭往上
    pen.backward(228)  #  Y軸退後 228;到底下
    timeStart = time.time( )   
    tree(pen, length, angle, ratio * (0.9+ random.random( )/10.0 ) )   ## 每次 Loop 會變 ratio
    print("Elasp time = {:.8f} sec.".format( time.time() - timeStart) )
    gg = input("quit or continue: ")
    if(gg == "q" or gg=="quit"): break;
    print("OK Go !")    
    turtle.Screen( ).clear( )
    pen.reset( );
    pen.color("#33fefe")   # cyan  
    if(random.randrange(100) > 60) : pen.color("yellow")    # 50% * 40% == 20%
    if(random.randrange(100) > 50) : pen.color("#55ff33")
print("bye!")
再試試以下這稍為改過的(用最前面說的"每次退回原處法"), 每個樹幹可能長出三個分支
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#turtle Graphics;  遞迴畫 Tree, 用前面的退回原處法, 但每次三分支! -- by tsaiwn@cs.nctu.edu.tw
angle, minLen = (50, 5)  #  往左 50 度, 樹枝長至少要 5 ## 改參數測試看看
import random
def tree(length):
    if length < minLen:      # 如果 minLen 用 1 會畫很久喔 !
           return
    psz = length/38
    if(psz < 1): psz = 1
    turtle.pensize(psz)
    turtle.forward(length)
    angL = angle
    angR = int(angle * (0.618 + random.random( )/2.0) )
    if(random.randint(0,100) > 50):
        tmp=angL; angL=angR; angR=tmp   # swap angL, angR  
    turtle.left(angL)
    tree(length * 0.618)
    turtle.right(angL + angR)  # 只是省一列 :-) # 繼續畫右邊的樹
    tree(length * 0.618)
    turtle.left(angR)    # 畫完 tree 記得轉回來, 目前烏龜頭往上 
    ang3 = random.randint(-25, 26)   # -25 ..  25 
    turtle.left(ang3);    ## 負的 left 其實就是 right ( ang3 在 -30..30 間)
    if abs(ang3) > 5:    # 若角度太小就不要再長第三分支 :-)
        tree(length*0.5)    ## 第三分支故意短一些些 
    turtle.right(ang3)     ## 畫完 tree轉回來,  目前頭往上 
    turtle.backward(length)   ## 退回剛進入這 function 時的點
    return     ##  其實最後的 return 可以不必寫
import turtle, time
timeStart = time.time( )
turtle.left(90)    ## 頭轉成向上
turtle.speed(0)
turtle.backward(228)    ## 退到畫面下方
tree(200)
timeEnd = time.time( )
print("Elasp time = {:.8f} seconds.".format(timeEnd - timeStart) )

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Turtle Graphics; coding=utf-8 ; 改參數然後測式看畫出啥 -- by tsaiwn@cs.nctu.edu.tw
angle, thick, steps = (59, 2, 360)  ## (59, 2, 360); (89, 2, 72); (29, 2, 120)
## angle -- angle to turn Left every time; try   59, 89, 123, .. 
## steps -- how many steps to draw 
speed = 0    # 1 ~ 11 fastest  ; 11 ==  0  == fastest  
import turtle             
turtle.setup(777, 777)           
pen = turtle.Turtle( )    # 新版也可用 turtle.Pen()  
colors = [ "red","blue","green","orange","purple","yellow",]
lenc = len(colors)
pen.speed(speed)
turtle.Screen( ).bgcolor("black")   # gray # turtle.bgcolor("black")   # gray
import time
start=time.time( )  
for x in range(steps):     # how many rounds  
   pen.pencolor(colors[x % lenc])  # cyclically use all colors
   pen.width(x/100 + thick)   #  pen.pensize(x/100 + thick)    # same 
   pen.forward(x)
   pen.left(angle) 
end = time.time()
print("Speed=", speed, ", Elasp time = ", end - start)
turtle.exitonclick()

  * Tkinter OnLine with Python 3
  * Trinker.io - Interactive Python Anywhere (這好像比較快)
  * 推薦初學者用這個REPL.it 線上撰寫與執行 Python 程式碼做練習;
          進入選 start coding > Python > Create REPL(免費註冊; 不註冊也能用)


# Turtle Graphics, 畫星狀 ---  改參數 n 然後測式看畫出啥 -- by tsaiwn@cs.nctu.edu.tw
# coding: utf-8   ;; 存檔編碼記得用 utf-8
n = 9  # 5, 7, 11, 15, 21, 33, 45, 59  # (請用奇數)
from turtle import *
Screen( ).bgcolor("#88fefe")   ## light cyan  
hideturtle()
colors = ["red", "green", "blue", ]
speed(9)  # 11 == 0 == fastest
pensize(2)
penup()
backward(100)
pendown()
angle = 180 - 180 / n
c = -1
for i in range(n):
    c = (c+1) % len(colors)
    color( colors[c] )
    forward(200)
    left(angle)
print("Done!")

# Turtle Graphics, 畫三角型 ---  改參數 n 然後測式看畫出啥 -- by tsaiwn@cs.nctu.edu.tw
# coding: utf-8   ;; 存檔編碼記得用 utf-8
angle, steps = (59, 48)  #  (28, 24); (58, 24); (58, 36); (59,60); (89, 72)  
from turtle import *
Screen( ).bgcolor(0.95,1,0.6)    #  light yellow
pensize(3)
speed(10)  # 11 == 0 == fastest ; 1 = very slow 
hideturtle()    # ht( )
colors = ["red", "green", "blue", ]     
penup()
goto(0, 0)
left(45)    # right-up 45 degree
pendown()      
def triangle( ):
    for i in (1, 2, 3):
        forward(150)
        left(120)  
c = -1
for i in range(steps):
    c = (c+1) % len(colors)
    color( colors[c] )  
    triangle( )
    left(angle)  
print("Done!")

# Turtle Graphics, 畫正方型 --  改參數然後測式看畫出啥 -- by tsaiwn@cs.nctu.edu.tw
# coding: utf-8   ;; 存檔編碼記得用 utf-8
angle, steps = (59, 11)   # (59, 11), (59, 6), (89, 8); (89, 13); (29, 12); 
length = 150   ##  邊長, 不要超過 300
import turtle
pen = turtle.Turtle( )    
turtle.Screen( ).bgcolor("black")
pen.pensize(3)
pen.speed(11)  #  11 == 0 == fastest  
colors = [ "red","blue","green","orange","purple","yellow",] 
def rect(p, length):    # 用 p 畫 正方型
  for i in range(4):
    p.fd(length)
    p.left(90)    
for i in range(steps):
  for c in colors:
    pen.color( c )  
    rect(pen, length)
    pen.left(angle)  
pen.ht( )   # Hide turtle
turtle.exitonclick( )

# Turtle Graphics, 畫圓形 ---  改參數然後測式看畫出啥 -- by tsaiwn@cs.nctu.edu.tw
# coding: utf-8   ;; 存檔編碼記得用 utf-8
angle, steps = (59, 30)  # (59, 11), (59, 6), (89, 8); (89, 13); (29, 12); 
length = 150
import turtle
turtle.setup(700, 700)
pen = turtle.Turtle( )
turtle.Screen( ).bgcolor("black")
pen.pensize(3)
pen.speed(11)  #  11 == 0 == fastest  
colors = [ "red","blue","green","orange","purple","yellow",] 
for i in range(steps):
  for c in colors:
    pen.color( c )     
    pen.circle(length)
    pen.left(angle)   
pen.ht( )
turtle.exitonclick( )

# Turtle Graphics  改參數然後測式看畫出啥 -- by tsaiwn@cs.nctu.edu.tw
# Example 2: Anklets of Krishna; -- modified by tsaiwn@cs.nctu.edu.tw
# In Python IDLE,  HELP >> Turtle Demo >> Examples >> lindenmayer
flen = 5   #  5,  5,  13, 13, 15, 21, 33
wlen = 10   # 10, 13,  13, 21, 15, 10, 15
from turtle import *
setup(500,500)      # Note that we did  " import * "
def replace( seq, replacementRules, n ):
    for i in range(n):
        newseq = ""
        for element in seq:
            newseq = newseq + replacementRules.get(element,element)
        seq = newseq
    return seq

def draw( commands, rules ):
    for b in commands:
        try:
            rules[b]()
        except TypeError:
            try:
                draw(rules[b], rules)
            except:
                pass
def A():
    color("red")
    circle(wlen,90)

def B():
    from math import sqrt
    color("blue")
    L = flen/sqrt(2)
    forward(L)
    circle(L, 270)   # 270
    forward(L)

def F():
    color("green")
    forward(wlen)

krishna_rules = {"a":A, "b":B, "f":F}
krishna_replacementRules = {"a" : "afbfa", "b" : "afbfbfbfa" }
krishna_start = "fbfbfbfb"

reset()
bgcolor("#cfcf66")
speed(0)
tracer(3,0)
ht()   # hide turtle
left(45)
drawing = replace(krishna_start, krishna_replacementRules, 3)
draw(drawing, krishna_rules)
exitonclick()    # exit when you click the figure/Graph

# Turtle Graphics, 畫圓、畫圓、畫圓 --  改參數然後測式看畫出啥 -- by tsaiwn@cs.nctu.edu.tw
# angle=30   # shift angle every time  # 30  , 29, 59, 89, 50, 250
# steps = how many steps to draw; every step draw nc circles 
angle, steps = (59, 30)  # (59, 30);(50, 30);(59, 11);(59, 6), (89, 8); (89, 13); (29, 12); 
pensize=2
nc = 6   # number of circles each time # 6, 5, 3, 
length = 100   ## Radius 半徑
speed = 11    # 10, 9, 8  ## 0 == 11 == fastest draw speed
import turtle
import math, random
colors = [ "red","blue","green","orange","purple","yellow",]
lenc = len(colors)
turtle.setup(700, 700)
turtle.Screen().bgcolor('black')   #  turtle.bgcolor('black')   
pen = turtle.Turtle()
pen.speed(speed)
pen.pensize(pensize)
pen.color(colors[0])

def drawCircles(p, c, size):
    for i in range(nc):
        p.color( colors[ c % lenc ] )
        p.circle(size)
        c += 1
        size -= 4

for x in range(steps):
    c = x % lenc   # c-th color  in colors[ ]
    drawCircles(pen, c, length)
    pen.left(angle)   
pen.ht( ) # hide turtle
turtle.exitonclick( )     # 滑鼠點一下圖片會結束

  *** 雪花飄飄 ***
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
## Python code to draw snowflakes fractal.   雪花碎形
##  https://www.geeksforgeeks.org/snowflakes-fractal-using-python/
import turtle, random, time
  
# setup the window with a background color 
wn = turtle.Screen() 
wn.bgcolor("#55ccdd")     # cyan 但別太亮會刺眼
  
# assign a name to your turtle 
elsa = turtle.Turtle() 
elsa.speed(0) 
  
# create a list of colours 
sfcolor = ["white", "blue", "green", "purple", "white", "magenta", "gray",] 
  
# create a function to create different size snowflakes 
def snowflake(size): 
    # move the pen into starting position 
    elsa.penup() 
    elsa.forward(8*size) 
    elsa.left(45) 
    elsa.pendown()    
    elsa.color(random.choice(sfcolor))    ## 選一個顏色
  
    # draw branch 8 times to make a snowflake 
    for i in range(8): 
        branch(size)    
        elsa.left(45)     
  
# create one branch of the snowflake 
def branch(size): 
    for i in range(3): 
        for i in range(3): 
            elsa.forward(8.0*size/3) 
            elsa.backward(8.0*size/3) 
            elsa.right(45) 
        elsa.left(90) 
        elsa.backward(8.0*size/3) 
        elsa.left(45) 
    elsa.right(90)  
    elsa.forward(8.0*size) 

timeStart = time.time( )  
# loop to create 21 different sized snowflakes  
# with different starting co-ordinates 
for i in range(21): 
    x = random.randint(-200, 200) 
    y = random.randint(-200, 200) 
    sf_size = random.randint(2, 5) 
    elsa.penup() 
    elsa.goto(x, y) 
    elsa.pendown() 
    snowflake(sf_size) 
  
elsa.up( ); elsa.goto(0, -228); elsa.setheading(90)
print("Elasp time = {:.3f} seconds.".format(time.time( ) - timeStart) )
# leave the window open until you click to close   
wn.exitonclick()   

* 建議進入以下這網站, 稍微看看並測試, 然後修改第二個程式的一些參數再試試!!

==> https://www.101computing.net/python-turtle-spirograph/
        建議改參數玩看看! 
    
   (市面上有賣該網頁內程式用到數學原理的文具, 叫做 "萬花尺", Design Ruler)
 
* 非廣告:這 "萬花尺", 一套, 一個圈圈尺+三個圈圈片, 才 NT$ 8元
   
* Python 支援 Object oriented(物件導向)所以可以寫 python class (類別)。
** 物件(Object)的概念與實際生活中用法很像, 用句點 . 表示 "的",
    例如張三的衣服的color(顏色)要 blue(藍色)可以寫成:
        張三.衣服.color = Color.blue
物件(Object) vs. 類別(Class)
物以類聚, 所以物件(Object)是某種類別(Class)的一個案例(instance; 實體; 複製品分身), 以真實世界的說法, 設計了一個類別等於是設計了該類物件的藍圖, 然後可以用該藍圖(類別)來製造(create;創建)出很多份該藍圖的實體(instance;案例)。
進階議題 -- Python class (類別)
      當你設計一個python class (類別), 通常要寫一個 __init__(self, 其它參數) 來幫忙做初始化的工作。
如果你學過 C++/Java/C#, 應該知道 Constructor (建構子) 是個特別的函數,會在物件生成(佔用到記憶體) 之時被呼叫!
      在 C++/Java/C# 的 constructor 就是與 class 同名的函數,在 Python 這個 __init__( ) 函數就是 Python 的 constructor 函數。 另外, 有個 __new__( ) 的函數就比較少會去寫,就像在 C++ 我們也很少會去 Override 類別(class)的 new 函數(C++ 稱呼 new 為 operator 運算符號); 如果想了解(建議先不要啦:-) Python 的 __new__ 用法與用途請點這"神奇的__new__"看看
  ==> 如果你想限制該類別(class)被用來產生物件最多有幾個, 那就須要寫 __new__ 函數。
點這看關於 Python 的 __init__ 用法舉例與說明(英文)
* 也可點這看關於 Python 的 __init__ 用法舉例與說明(中文)
* Python 類別(class)內所有的函數至少要有一個參數,
      第一個參數通常用 self (只是建議, 不是規定, 你用 ggyy 也可以:-);
      這第一個參數永遠指向目前在執行該函數的物件,
      所以這 self 類似 C++ 的 this;
      但是, C++ 一定叫 this, Python 可以不叫 self 就是了。
* Python class (類別) 的 destructor 其實不是 destructor !
      啥啊?
      阿就是那個 __del__(self) 的函數, 並不保證在物件被 del 之時執行,
      它是在物件佔用的記憶體被"回收"時才執行, 所以嚴格說來, 它是 finalizer 函數。(看不懂先不管啦:-)
* Python class 的 私有成員(private member)以及 getter 與 setter
      為了確保所設計之類別的物件內容不會被外部函數不小心改掉,
      Python 建議儘量把 class 內的成員設為私有的(private),
      這很簡單, 只要在成員變數名稱左邊加一個 "_" 底線號(underline)即可!
      當然, 這樣一來, 有需要時, 就必須幫忙該 private 的成員撰寫 getter 和 setter 函數。

    (看不懂? .. 也是先先不管啦:-)
==> 點這跳到後面看更多關於 class 類別說明與範例
很重要所以再說一次..
**
注意! 注意! 注意!  
      Python 沒有 ++ 和 -- 喔! 雖然寫了不會報錯, 但其意義和 C/C++/Java 不同喔!!!

** 也是進階議題 ..
How to Use Generators and yield in Python(開啟大檔案很有用)(讚)
Python 資料庫教學
淺談 Coroutine 協程使用方法
Async IO in Python: A Complete Walkthrough
python的asyncio模組(一):異步執行的好處
Generators are NOT Coroutines

TOP        
     
  以下再把 Python 各控制語句(Control statements)語法的連結列出方便點閱:   * Python if ...else (假如下雨記得要把帶的傘打開否則藏在包包內即可)
 
* Python for Loop (迴圈)
 
* Python while Loop https://www.programiz.com/python-programming/while-loop
 
* Python break (中斷離開) and continue (繼續下一回合, 但放棄目前這回合剩下的)
      ==>   for Loop 和 while Loop 最要注意的就是 break continue
 
* Python pass (這裡沒事情) ( ㄟ 很多遊戲都有 pass 這招啊 )
 
* 範例: Python 寫 LCM (最小公倍數) 和 GCD(最大共同除數; 最大公約數)
*** 來看看 pass 使用的時機 .. 就是至少要寫一句但又不想做任何事情時:
    **可以到這網站 https://REPL.IT 線上輸入或貼上 Python 程式碼測試
test38$
test38$ cat pp.py
for i in range(1, 10, 1):     # 剛好是 10 那次不會做, 所以意思是 i 一定要小於 10   
   r = i % 2
   if r == 0:  # 偶數, 不想做事; 其實你可以改檢查 r == 1
      pass   #  規定至少要寫一句, 但不想做事, 只好寫 pass
   else:  # i is 奇數
      print("這 i = ", i, " 是奇數");

print("Now i=%d"  % i);    # Python 結尾有沒有 ; 分號都可以
print("===bye===");
test38$ python3 pp.py
這 i =  1  是奇數
這 i =  3  是奇數
這 i =  5  是奇數
這 i =  7  是奇數
這 i =  9  是奇數
Now i=9
===bye===
test38$
   *** 注意 Python 的 For Loop 結束時, i 是最後一次做的值;
       但是, C/C++/Java 是下一個值, 以類似此例來說, i 應該 是 10; 可到 C++線上網站測試:
#include <stdio.h>
int i;
int main( ) {
   for(i=1; i < 10; i+=1) {
      int r = i % 2;
      if( r != 0) printf("這 i = %d 是奇數\n", i);
   }
   printf("Now i = %d\n===bye===\n", i);   // 10
   return 0;
}

*** C++ Online -- -- 到這網站 https://www.jdoodle.com/ 線上玩 C++/C

一個年紀比較大的人問一個年輕人:你有看過金庸小說嗎?
年輕人:沒有,只有看過電視劇。
大人:那你知道金庸寫的十四部小說的書名的第一個字,
    串起來會成為一首詩:
  「飛雪連天射白鹿,笑書神俠倚碧鴛」嗎?
年輕人:不知道。 但是我有看 JK 羅琳的小說,
      你知道她寫的七本小說的書名的第一個字串起來是什麼嗎?
大人:不知道!
年輕人:那就是 .. 來問問 Python 如何說:
test38$  
test38$ python3
Python 3.6.5 (default, Aug 26 2018, 13:30:20)
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> "哈 " * 7 
'哈 哈 哈 哈 哈 哈 哈 '
>>> gg="嘿" * 3 + "哈 " * 7
>>> print(gg) 
嘿嘿嘿哈 哈 哈 哈 哈 哈 哈
>>> print("呂秀蓮說過: " + gg[:3] + " -- " + gg[3:]) 
呂秀蓮說過: 嘿嘿嘿 -- 哈 哈 哈 哈 哈 哈 哈
>>>  print(gg[2:3]) 
嘿
>>>  print(gg[2:4])   # gg[] 的第 2 元素到第 4 之前(阿就是到第 3 元素啦)
嘿哈
>>> exit() 
test38$ 
test38$ 
大人:這 Python 這麼厲害, 連這也知道 !@#$%*...

  $$ 如果你不花錢就不想學, 這個要錢的Python3教學已經有近50萬人買過應該不錯      
      👍   在 Udemy 的免費Python3教學也二十幾萬人看ㄟ, 應該不錯才對 ( 也有放在 Youtube.com )
  $$ 這個 /python3-chinese好像是老共錄製的教學影片(只九百多人買過 :-)   (老共的定價比較便宜:-)
  $$ 還有這 /intro-to-python-ds-1 則是台大畢業生郭老師錄製的教學影片 (有五千多人買過, 贏老共很多 :-)

** 線上製作 GIF 工具 :       https://ezgif.com/       https://gifmaker.me/
** 線上把動畫 GIF 變小 :     https://ezgif.com/resize     https://resizeimage.net/
** 線上圖片編輯工具(只比Photoshop差一點點):   https://pixLR.com/editor
        (進入後它會說需要 Flash, To enable flash, .. Click here 阿就給他點下去) 改用新版 pixLR.com/x/  

TOP        
     
 
*** Pythonanywhere :Host, run, and code Python in the cloud!(選Free的)
      -- 有人不推薦 PythonAnywhere, 推 sense.io DataJoy, HeroKu, OpenShift ...
*** Heroku安裝使用教學 還有 這Django Girls用 Heroku 部署Django網站 的教學文件(很詳細)
    以及 這篇教你 Deploy a Flask App To Heroku (部署 Flask 網站到 Heroku) (中文啦)
    P.S. 可在 Heroku 免費部署網站, 但免費的網站每天至少要休息六小時 !
   
*** 想要在自己電腦的 Windows 上玩 Python ? (要玩大數據分析的建議抓 Anaconda)
  * 當然要抓 Python 回來安裝(Install)才能用啦, 不過 Python 有很多版本, 抓哪個好呢 ?
      👉 通常是抓官方網站的標準版, 但如果要玩大數據分析的則建議抓 Anaconda 版本
  * 標準版當然是到 Python 官方網站抓: https://python.org
      請依據你的電腦作業系統(OS)抓正確 Python 版本回來安裝, 建議不要抓最新的, 也不要再用 Python 2.x 了啦 !
      如果用 Windows,
      建議點這抓3.6.8 會連到 python.org/ftp/python/3.6.8/python-3.6.8-amd64.exe

      (2020 Update: 現在改 建議抓 3.7.7 版本 25.5MB)
      安裝過程很簡單, 阿就看要不要改預設的安裝路徑, 然後大部分都只是按"下一步" 或 "確定"
      官方的版本安裝時要特別注意! 要特別注意! 要特別注意!!!
      很重要所以說三次:
         就是要記得勾選 " Add Python ... to Path" 這項讓它把安裝好的 Python 路徑加入系統PATH

      阿不然事後還要找懂系統 PATH 概念的人幫你修改系統的 PATH 路徑, 很麻煩ㄟ !(其實也很簡單:-)
      需要修改 Path 路徑請點這 (建議砍掉重新安裝比較快 :-)
      這個版本安裝好之後可以使用 Python IDLE (自帶的整合開發環境),
      也可以在 CMD 命令視窗使用 python 命令(注意打 python 就好, 不用打 python3)
      可以點這裡看看別人的教學文(其實很簡單啦 !)
       ==> Or Click here to see Tutorial for Python 3 Installation
      也可以點這裡看看我在交大計中(已安裝 Python 的電腦上)使用 Python 的範例說明(也很簡單啦 !)

  * 另外, PyCharm 號稱是最強大的 Python IDE 並且5.0+版夾帶許多網頁相關套件 !
      可抓免費教育版 PyCjarm

  * 也可 點這抓 Anaconda   以及 使用 Jupyter Notebook   點這看 Jupyter Notebook 使用介紹
      (這有 台大學生寫的簡易教學老共寫的Anaconda教學老共寫的Jupyter教學 )
  * 關於Jupyter Notebook介紹及安裝說明   https://jupyter.org   Jupyter 專案計畫

      *關於使用 Anaconda/Jupyter, (簡單說就是用瀏覽器開網頁使用 Python 3)
      也可以點這裡看看我在交大計中(已安裝 Anaconda 的電腦上)使用 Jupyter 測試 Python 的範例說明
(也是很簡單啦 !)
      簡單說, Jupyter 就是讓使用者透過瀏覽器使用 IPython 來編寫/執行 Python 程式啦 !     (IPython 就是 Interactive Python)
Photo by Jupyter Documentation
      ** 你可以把Anaconda相關的東西都安裝在自己 PC Windows 上 ( 廢話 :-)
  **
也可以 透過 PuTTY SSH Tunneling 使用 VPS 上的 Jupyter Notebook  
          (就是說, PC Windows 端可以沒有任何和 PyThon 有關的東東 !)
 
  ** 想把跑在自己電腦的網站公開為 https://某網址 (想寫 LINE 聊天機器人或 FB 機器人時很好用)
可以利用 ngrok 服務或用 serveo.net類似的服務,   Is ServeO.Net Alive ?   Is ngrok.com Alive ?
請參考 https://iottalk.vip/604/#NGROK   (其實這是我計算機概論課程習題的加分題:-)  
*** 關於 ngrok 服務,這裡也摘述一下:
網站相關的實用小常識
如何讓內網(Intranet)的網站可以讓外網全世界的人連進來?
就是你的網站跑在 Private IP (例如 192.168開頭的)電腦上, 但想讓別人用啦!
很簡單.. 不要錢(當然付錢可有更多服務),
  ==> 用 ngrok 服務即可, 抓 ngrok 來安裝, 然後設定一下就可用了!
o Download ngrok:
      https://ngrok.com/download
o ngrok on github:
      https://github.com/inconshreveable/ngrok
 

註: PuTTY SSH Tunneling 可讓你 PC Windows 上 http://localhost:8080 其實連到遠端機器上的 localhost:8888
      * 這裡的 8080 和遠端 8888 都是自己可以選擇設定的
      * localhost 另一個代稱是 127.0.0.1 都是表示自己這部電腦。
 
其實我在這 iottalk.vip 內已經安裝了 Anaconda 和 Jupyter notebook,
你可以 透過 PuTTY SSH Tunneling 使用 VPS 上的 Jupyter Notebook

或是正常 SSH 登入iottalk.vip之後, 用以下命令把 jupyter notebook 跑在開放的 port: (此例用 8088)
或是正常 SSH 登入iottalk.vip之後, 用以下命令把 jupyter notebook 跑在開放的 port: (此例用 8088)

或是正常 SSH 登入iottalk.vip之後, 用以下命令把 jupyter notebook 跑在開放的 port: (此例用 8088)
(很重要所以說三次:-))
所謂開放的 Port 意思是你執行 jupyter notebook 時 IP 要用 --ip=0.0.0.0  (port 任意)
例如, 登入後做以下兩個命令即可在任何地方用瀏覽器 指定port 8088 啟用 Jupyter
(但是需要密碼喔! 會出現在 SSH CMD 窗內)
    source `which getconda`
    jupyter notebook --ip=0.0.0.0 --port=8088
# 再說一次, 用如下的命令把 jupyter notebook 在 Server 端跑起來等 Client 端:
source `which getconda` # 這是啟動 Anaconda 的 Python 環境
conda info # 這句只是顯示 Anaconda Python 相關訊息
jupyter notebook --ip=0.0.0.0 --port=8088 # 啟動 Kupyter Server
好啦, 現在可在任意 PC 上用瀏覽器在網址列打 iottalk.vip:8088
不過這時需要複製剛剛終端機視窗跑 jupyter notebook 時吐出的 token 來當密碼!
* 點這看 Jupyter Notebook 使用介紹 (Windows 版 jupyter 命令語法不太一樣)
以下示範 Tunnel (地道)從 Windows 的 53388 連去 iottalk.vip 的 8888
   
   

在瀏覽器網址列打入 localhost:53388 或 127.0.0.1:53388
   
注意, 若很多人用 iottalk.vip 則 8888 可能已經被用掉 ! 阿你就改試其他 Port 啦 !
Q: 為何網路上找不到說要做 source `which getconda` ?
      (注意夾住 which getconda 的 ` 是重音符號, 在鍵盤左上角附近, 不是單引號 ' 喔!)
  A: 因為 getconda 是我寫的一個腳本(Script)檔案 :-)   -- 不是唱為你守候那個The Script喔 !
      讓你做 source 該檔案 就會啟動 Anaconda 環境 !
      `which getconda` 就會自動變該檔案完整路徑(path name)
Q: 奇怪, 阿不是說沒root權限的原則上 port 應該用 1024 到 49151 嗎?怎用53388?
  A: 阿既然說是"原則上"就是可以偶爾偷用啊, 哈哈 ! 哈 :-)

  * <新手起步>建立適合windows的python資料分析及機器學習開發環境(要免費註冊看, 不然它會煩你)
      因為該網站沒註冊多看幾篇就很煩, 我把上面那篇偷回來放我網站這方便大家看:-)
      點這看 Python安裝心得 (寫這如何安裝的文章也能拿來賺Google廣告費, 真的服了ㄟ)
  * 如果不要胖胖的 Anaconda 只要純 Python 也可以到 Python.org 官網去抓來安裝

  PyCharm 有 EDU 免費版 https://www.jetbrains.com/pycharm-edu/
 
*** Python Online -- 到這網站 https://REPL.IT 線上玩 Python
    ** 這 REPL.IT 也有提供 Command Window 讓你可以暫時玩 Linux 命令 (但命令有限)
    ** about REPL.IT (wiki)     關於 REPL.IT 介紹請點這   或   看 Youtube 影片介紹 REPL.IT

*** C++ Online -- -- 到這網站 https://www.jdoodle.com/ 線上玩 C++/C
    ** 其實 這 Jdoodle.com 也可以線上玩 Python       Jdoodle.com FAQ

*** 也可以用 Google Colaboatory 在線上玩 Python 與人工智慧的 TensorFlow
TOP        
     
     
** EduTalk 總部在交大     **台大石明豐教授 Vpython+Physics 課程文件(pdf,5.28MB)
*** 到 https://EduTalk4.NCTU.edu.tw/ 線上 玩轉 VPython
      (如果EduTalk4不能用, 把 4 改為 3 或 2, 因為 EduTalk4 好像有時會被高慧君老師玩壞掉 :-)
  ** 到 GlowScript.org 偷範例來貼入 EduTalk4 NCTU 測試並研究
      (如果EduTalk4不能用, 把 4 改為 3 或 2, 因為 EduTalk4 好像有時會被高慧君老師玩壞掉 :-)
      o 注意抓回的程式碼可能第一句需要用 # 註解掉 才不會有錯誤 !
  ** 這是 vPython 的家 https://www.vpython.org/
  ** 到 建中賴老師(管理 EduTalk3) 和 曾老師(管理 EduTalk2) 的 特色課程
          去 偷範例來貼入 EduTalk4 NCTU 測試並研究

      (如果EduTalk4不能用, 把 4 改為 3 或 2, 因為 EduTalk4 好像有時會被高慧君老師玩壞掉 :-)
      o 注意抓回的程式碼需檢查該凹入的句子是否需手動打入空白 (因前置空白可能不見了!)
  ** 到 南港高中高慧君老師 的網站偷範例來貼入EduTalk4 NCTU 測試並研究
    * 點 課程 > VPhysics 物理模擬 裡面有很多範例/教學
    * 注意裡面向量(33, 88, 55)要改為以下這樣:
      vec(33, 88, 55) 或 vector(33, 88, 55) 也可
      如果出現 materials is not defined 錯誤..
        .. 就把 材質球materials相關刪除即可(或把 materials 改用 textures 看看)
  ** 例如, 以下是把高慧君老師"自由落體"範例稍微修改過:
#  高慧君老師 http://drweb.nksh.tp.edu.tw/student/lesson/F03/
# -*- coding: utf-8 -*-
# 匯入視覺化套件
from visual import *
freq = 200    # rate
delta = 1.0/freq
# 1. 參數設定
#加速度
a = -9.8    #加速度值,在 x、z 方向為 0,在 y 方向為 g=-9.8 m/s^2
#速度
vy = 0      #球的 y 方向速度(公尺/秒),初始值為0
#高度
h = 10.0    #球的初始高度,單位為公尺
#時間間隔
dt = 1.0/freq   # 0.001  #畫面更新的時間間隔,單位為秒
#經過時間
t = 0       #模擬所經過的時間 ,單位為秒,初始值為0

# 2. 畫面設定
#畫布
scene = display(center = vec(0, h/2, 0), background=vec(0.5,0.6, 0))
#參考地板
floor = box(pos=vec(0,0,0), length=15, height=0.005, width=5)
#球
ball = sphere(pos =vec(0, h, 0), radius=0.2, color=color.blue)
#次數
number = 0
minvy = 999
label_info = label( pos=vec(5,10,0), \
           text='Time:{:.3f}\nSpeed: {:.2f}\nMinSpeed: {:.3f}\n高度: {:.2f} 第{}次反彈'.\
           format(t,vy,minvy,ball.pos.y, 0)) 
# 3. 描述物體的運動
while number < 66: 
        rate(freq)
        t += delta
        # 速度 = 速度 + 加速度 * 時間間隔
        vy = vy + a * dt 
        if ball.pos.y < 0.5:  # 0.2*2 +0.1
           gg = abs(vy)
           if gg < minvy : minvy = gg 
        # 位置 = 位置 + 速度 * 時間間隔
        ball.pos.y = ball.pos.y + vy * dt
        label_info.text = \
             'Time:{:.3f}\nSpeed: {:.2f}\nMinSpeed: {:.3f}\n高度: {:.2f}\n 第{}次反彈'.\
             format(t,vy,minvy,ball.pos.y,number) 
        if ball.pos.y < ball.radius:  #radius 0.2 
                vy = -vy*0.9
                number = number + 1
                if abs(vy) < (ball.radius/2.0) : break; 
上面我改過南港高中高慧君老師範例貼到 EDuTalk 任意範例 Program 視窗, 點 Animation 看看
    (如果EduTalk4不能用, 把 4 改為 3 或 2, 因為 EduTalk4 好像有時會被高慧君老師玩壞掉 :-)
補充說明: Python 檔案的前面兩列中如果是註解且有出現 coding: 或 coding=
    則其後的字會被認定是指定的檔案所用的文字編碼! (檔案存檔最好指定用 utf-8)
    請注意, 只有寫在前兩列且是註解列才有效喔 !
高慧君老師還有一個很棒的教學網站, 很適合想認真學程式的高中同學(大一入門也可:-) !
      --- 如果網站掛了(在台中科大計中), 請改點高慧君老師另一個網站

  **以下則是貼入建中老師的範例 然後 點 Animation :
      (注意 可能需要修改程式碼的凹入狀況 !)
     
  ** 到 台大 vPhysics 物理 + Python 網站 https://vphysics.ntu.edu.tw/

  ** 來玩 IoTtalk 物聯網應用 -- 連到 demo.iottalk.tw
   *** 想玩 IoTTalk 物聯網應用的可以點這看 IoTTalk 物聯網應用操作入門

  ** 關於 VPython 補充說明:
      在 IoTtalk 系統首頁 VPython List 之下的視覺化網頁應用(Visual Web Application)
      都是用 VPython 視覺化的語言(其實是程式庫模組)寫的應用 !
      VPython 的首頁 就說道:
          VPython 是 3D Programming for Ordinary Mortals (凡人用的 3D 程式設計)

  * 想體驗 VPython programming,
      請點這連到 https://EduTalk4.NCTU.edu.tw/ (免費註冊 Sign up)
    (如果EduTalk4不能用, 把 4 改為 3 或 2, 因為 EduTalk4 好像有時會被高慧君老師玩壞掉 :-)
  * 想看更多 VPython programming 範例,
      請點這連到 VPython 官方的 Examples

      VPythonPython中一個稱為 Visual 的模組所擴充而來。其原始架構是由Carnegie Mellon University的大學生 David Scherer 在2000年開發出來,核心為Python 這個易學的程式語言,以其建構的三維繪圖模組來描述虛擬的物理世界,讓使用者可以輕易的利用程式來做三維空間的物理繪圖,具備有動態的時間演進和不同的視角觀察,讓學生可以更直覺的利用程式來學習物理,尤其是需要視覺化和動態觀察的物理現象。

      VPython 目前有多個版本被廣泛使用,除了原本的單機版的 VPython 之外,另有在網頁上可執行的GlowScript(EduTalk 就是用這 Javascript 實作的版本),與新世代的vpython-jupyter計畫(就是提供 API 讓 VPython 可以在網頁執行)。
   
    在IoTtalk 系統裡面的 VPython List 各應用 以及在 EduTalk4.NCTU.edu.tw 都是在瀏覽器用 GlowScript 執行VPython 程式碼)。


    (如果EduTalk4不能用, 把 4 改為 3 或 2, 因為 EduTalk4 好像有時會被高慧君老師玩壞掉 :-)  

    TOP        
     

Python 支援 Object oriented(物件導向)所以可以寫 python class (類別)。  
再談 Class(類別) 與 Object(物件)   以及 Python 的 模組(Modules) 與 套件(Packages)
Class (類別): 把資料以及處理該些資料的函數封裝(encapsulate)在一起稱為 class; 例如人類、動物。
Object (物件): 某個類別(class)的一個案例(Instance). 例如張三和李四都是人類的案例。
      An object is an instance of a class.
      物件必定是某個類別的一個案例(實體)。

注意 1: 函數(function, 函式)、方法(methods)、行為(behaviors)、以及動作(operations)都是同義詞。
注意 2: 屬性(property)、資料(data)、欄位(field)、以及變數(variable)這些也算是同義詞。
* 簡單來說, Class (類別) 裡面就是包括函數(函式)和變數(以及不會變的變數就是常數)。
* 我寫了一個簡單的 python class 讓大家可以測試並研究 :
    constructor, getter, setter, member function;
    public instance variable and private (用 __ 起頭) instance variable;
    class shared variable -- also can be private and/or public
    重要原則: 儘量把變數藏起來(__開頭), 必要時寫 getter and/or setter 函數!
# coding=utf-8   ; demo Python class usage; by tsaiwn@cs.nctu.edu.tw
class Egg:
   __xxx = 5    # private shared
   abc = 0    # public shared
   def  __init__(self, a, b):
      print("Constructing ..", a, b)
      self.x = a
      self.__y = b
      Egg.__xxx += 1
      Egg.abc -= 1
   def getY(self):
      return self.__y
   def setxxx(self, arg):
      Egg.__xxx = arg
   def getxxx(self):
      return Egg.__xxx
   def getabc(self):
      return Egg.abc
   def getx( ):
      return Egg.__xxx
   def setx3(arg):
      Egg.__xxx = arg

Egg.__xxx = 100  #  不要這樣! 注意這不是 class Egg: 內的那 __xxx
Egg.abc = 200   # OK  這是 class Egg: 內的 那個  abc

gg=Egg(33, 88)
## Constructing .. 33 88

yy=Egg(55,66)
## Constructing .. 55 66
print("Egg.__xxx = ", Egg.__xxx)  # 100  注意不是 class Egg: 內的那 __xxx
print("Egg.getx() = ", Egg.getx())   # 7
print("Egg.getxxx(Egg) = ", Egg.getxxx(Egg))  # 7
print("Egg.abc = ", Egg.abc)  #198

print("gg.x == ", gg.x)  #33
## print("gg.__y == ", gg.__y)  # Error because private member
print("gg.getY() == ", gg.getY()) #88
print("gg.getxxx( )= ", gg.getxxx( ))  #7
print("Egg.getxxx(Egg)= ", Egg.getxxx(Egg))  #7
print("yy.getxxx( )= ", yy.getxxx( ))  #7
## print("yy.__y == ", yy.__y)  # Error because private member
print("yy.getY() == ", yy.getY())  #66

Egg.setxxx(Egg, 333)  # Python 3, 2 all OK
print( "Egg.getx( ) = ", Egg.getx( ) )
gg.setxxx(500)
print( "after gg.setxxx(500), Egg.getx( ) = ", Egg.getx( ) )

Egg.setx3(666)   #  Python 3 OK
print("Do  Egg.setx3(666)  NOW")

print("yy.getxxx( ) = ",  yy.getxxx( ))  #666
print("gg.getxxx( ) = ",  gg.getxxx( ))  #666
print( "Egg.getxxx(Egg) = ", Egg.getxxx(Egg) )  # 666
## print( "Egg.getxxx( ) = ", Egg.getxxx( ) )  # Error
print( "Egg.getx( ) = ", Egg.getx( ) )  #666   this OK!
###
Egg.setxxx(Egg, 888)
print( "after Egg.setxxx(Egg, 888), Egg.getx( ) = ", Egg.getx( ) )
print( "Egg.getxxx(Egg) = ", Egg.getxxx(Egg) ) #888
print("gg.getxxx( ) = ",  gg.getxxx( ))  #888
print("yy.getxxx( ) = ",  yy.getxxx( ))  #888
print("=== Bye!")

==> 點這跳到前面看關於 object 與 class 概念

Python Module (模組): a single Python .py file.
Python package (套件): several Python files in a directory. (with an additional __init__.py file.)

注意: 該目錄若要當一個 package 則裡面必須有 __init__.py 這個檔案   (即使是空的也可以)
Python 模組 (Modules) 與 套件(Packages)
在 Python 程式中, 所謂的模組(Module) 其實就是一個 .py 檔案(對啦, 就是這麼簡單:-)
Simply, a Python module is a file consisting of Python code.
A module can define functions, classes and variables.
Grouping related code into a module makes the code easier to understand and use.
import 語句或 from import 語句只會在第一次匯入模組時執行模組中第一層(top level)的程式碼, 重複import同一個模組, 並不會使得模組中的程式碼被重複執行多次 !
所以, 我們常常在有些 .py 檔案中有類似以下這種句子:
if __name__ == '__main__':    
      ggyy( )   # 通常是寫 main( ) 啦

?為甚麼會這樣寫呢 ?
還有,
所謂的套件(Package), 其實就是一個目錄(對啦, 也是這麼簡單!), 裡面可以有很多個 .py 檔案(模組);
Similar files are kept in the same directory, for example, we may keep all the songs in the "music" directory. Analogous to this, Python has packages for directories and modules for files.
但是, 剛剛就說過了, 就是該目錄若要當一個 package 則裡面必須有 __init__.py 這個檔案

Life is easy. Why do we make it so hard?

A class is a construct that defines a collection of properties (data/variables) and methods (functions). You can think of it as a Template which can be used to create an Object.

另一種講法: Objects are an encapsulation of variables and functions into a single entity. Objects get their variables and functions from classes. Classes are essentially a template to create your objects.

In encapsulation, the variables of a class will be hidden from other classes, and can be accessed only through the methods of their current class. Therefore, it is also known as data hiding. Usually we declare the variables of a class as private. And then provide public setter and getter methods to modify and view the variables values.

A package is a collection of Python modules: while a module is a single Python file, a package is a directory of Python modules containing an additional __init__.py file, to distinguish a package from a directory that just happens to contain a bunch of Python scripts.
再說一次, 注意: (很重要, 所以說三次:-)
    該目錄若要當一個 package 則裡面必須有 __init__.py 這個檔案
    否則, 該目錄就只是一個 mortal 凡人, 阿不是, 我是說..就只是一個普通目錄 !

A namespace is basically a system to make sure that all the names in a program are unique and can be used without any conflict. You might already know that everything in Python—like strings, lists, functions, etc.—is an object. Another interesting fact is that Python implements namespaces as dictionaries.
注意每個目錄(Directory)內本來就不能有同名的檔案 !

 
虛擬環境(Virtual ENV) + 枕頭(PILlow) 與影像處理 (Image Processing)
  ? Why the Need for Virtual Environments?
以下將介紹簡單影像處理:
    (a)建立一個Python虛擬環境;
    (b)安裝 pillow 套件;
    (c)用 art.py 做影像處理把圖片檔轉為 .txt 文字藝術
* PIL == Python Image Library;   PILlow 是 PIL 的一個 fork(分支)
* 注意, Pillow 和 PIL 不可以同時安裝, 跟魚與熊掌一樣, 只能貳擇一 ! (不過, 孟子選擇熊掌, 真會吃 :-)
    但是, 你可以把它們安裝在不同的虛擬環境(Virtual ENV), that's Why We Need the Virtual Environments !
* 當 superuser (root) 沒幫安裝某些套件時, 你可以在隔離的虛擬環境自己安裝額外套件
* Python3 內建 venv 模組, 不需像Python2再安裝 virtualenv
* 要建立隔離的虛擬環境很簡單: (所有 Unix/Linux 以及 Mac OS 通用)

      mkdir haha # 造一個子目錄 haha (不造也可以, haha 是自己隨便取名的)
      cd haha # 進入 haha 子目錄準備開始工作
      python3 -m venv myvenv # 會建立子目錄 myvenv, 是一個 Python 虛擬環境
      source myvenv/bin/activate # 啟動虛擬環境

**Windows 系統則上述的 source 那句 改如下: (Windows python 不必打 3)
    myvenv\Scripts\activate

**以下用到的 art.py 是來自網路:
      https://gist.github.com/Ronald-TR/1bb452206b97b470a2b74942de984acf

mkdir test543  # 造個子目錄 test543  方便區隔工作
cd test543     # 進入該子目錄
python3 -m venv ggyy  #  製造一個虛擬環境放在子目錄 ggyy
source ggyy/bin/activate   #啟動虛擬環境 ggyy

nano art.py
# 把以下(往下捲一些些)程式碼複製貼入編輯窗
# 貼入完畢後, 敲 CTRL_S 存檔, 敲  CTRL_X 結束 nano

# 抓一張圖片檔來測試, 可自己找, 或抓這張恭喜豬年圖片 2019pig3.png
wget https://iottalk.vip/static/img/2019pig3.png   # 抓 圖片檔 2019pig3.png
python art.py 2019pig3.png

# 會有錯誤說不認識枕頭 (PILlow)

pip install pillow    # 安裝 pillow 套件
# 需要幫忙按 ENTER

python art.py 2019pig3.png
# 好了, 把文字藝術檔印出來看看

cat 2019pig3.txt

deactivate   # 離開虛擬環境 ggyy
pwd   #  看看身處何處 ?  (目前在哪個目錄 ?)
cd ..   # 回上一層目錄 

**以下用到的 art.py 是來自網路:
      https://gist.github.com/Ronald-TR/1bb452206b97b470a2b74942de984acf
# art.py
from PIL import Image
import os
ASCII_CHARS = [ '#', '?', '%', '.', 'S', '+', '.', '*', ':', ',', '@']

mywidth = 128

def scale_image(image, new_width=mywidth):
    """Resizes an image preserving the aspect ratio.
    """
    (original_width, original_height) = image.size
    aspect_ratio = original_height/float(original_width)
    new_height = int(aspect_ratio * new_width *3.0/4.0)
    new_image = image.resize((new_width, new_height))
    return new_image

def convert_to_grayscale(image):
    return image.convert('L')

def map_pixels_to_ascii_chars(image, range_width=25):
    """Maps each pixel to an ascii char based on the range
    in which it lies.
    0-255 is divided into 11 ranges of 25 pixels each.
    """
    pixels_in_image = list(image.getdata())
    pixels_to_chars = [ASCII_CHARS[pixel_value//range_width] for pixel_value in
            pixels_in_image]

    return "".join(pixels_to_chars)

def convert_image_to_ascii(image, new_width=mywidth):
    image = scale_image(image)
    image = convert_to_grayscale(image)
    pixels_to_chars = map_pixels_to_ascii_chars(image)
    len_pixels_to_chars = len(pixels_to_chars)
    image_ascii = [pixels_to_chars[index: index + new_width] for index in
            range(0, len_pixels_to_chars, new_width)]

    return "\n".join(image_ascii)

def handle_image_conversion(image_filepath):
    image = None
    try:
        image = Image.open(image_filepath)
    except Exception as e:
        print("Unable to open image file {image_filepath}.".format(image_filepath=image_filepath))
        print(e)
        return

    image_ascii = convert_image_to_ascii(image)
    f = open(os.path.splitext(image_filepath)[0]+'.txt','w')
    f.write(image_ascii)
    f.close()

if __name__=='__main__':
    import sys
    image_file_path = sys.argv[1]
    print("Use {} to process 圖片檔 {}".format( sys.argv[0],  sys.argv[1] ));
    handle_image_conversion(image_file_path)
    ans = os.path.splitext(image_file_path)[0]+'.txt'
    print(" 文字藝術圖在 {}\n 你可以  cat {}".format( ans, ans ));
* 如果要用 Python 寫 GUI 的程式,可以點這看 Python GUI 設計影片教學(with Python Tkinter)
* 要更詳盡 GUI 教學,可以點這看 Python GUI 詳細影片教學(也是 with Python Tkinter)(六小時)
TOP        
     

Python 支援 Object oriented(物件導向)所以可以寫 python class (類別)。    
物件導向概念(Object Oriented Concept)

      物件導向(Object Oriented)主要是類比於實際世界的物件(Object),例如汽車是一種類別(Class), 房車與跑車都是一種汽車, 表示房車是汽車做了一些修改或擴充(extends)的新類別, 跑車也是汽車做了一些修改或擴充(extends), 所以房車和跑車都是繼承(inherits)自汽車的類別, 或說房車與跑車都是 extends 汽車, 都是從汽車擴充(extends)而來!
      物件(Object)有時與類別(Class)被混為一談, 例如某人說:"請幫我設計一個 ??? 的物件", 其實他的意思應該是 要說"請幫我設計一個 ??? 的類別(class)"才對, 關於物件與類別的討論稍後再說
      請注意, 有些電腦語言雖然提供物件設計與使用概念, 但是不提供把已經寫好的物件類別"擴充"(extends, 即繼承inherits), 則該語言不是物件導向(Object Oriented), 只能算是以物件為基礎的語言(Object Based Language)。
      真正的物件導向應該包括以下四大特性:
    (1)封裝 Encapsulation: 把資料(data)與跟該些 data 有關的函數(function)或方法(method)封裝到一個類別(class)內
          這與真實世界很類似, 鬧鐘裡面有許多元件, 各元件有其功能(function; 沒錯, 功能的英文也是function), 全部被封裝在一起變成一個產品, 只露出給我們看的以及給我們按的按鈕或旋鈕。

    (2)資訊隱藏 Information hiding: 只有類別內的函數或方法可以存取物件內私密的資料(private data)
          這更是類比於真實世界, 想一想你要設定鬧鐘會把鬧鐘拆開用手去撥動其指針嗎? 你需要動到其內部的電子零件嗎? 所以設計物件的類別時有個重要原則:
        (a)資料(屬性)儘量藏起來(hide), 只有自己的函數可以存取內部資料,
        (b)函數(功能)儘量公開(public)讓外界使用 !

          意思是資料儘量用 private 修飾語隱藏在內部, 只有內部的函數可以存取它, 函數則儘量用 public 修飾語開放給外部直接使用, 就像鬧鐘外表有一些按鈕或旋鈕。

    (3)繼承 Inheritance 或 擴充 extends : 可以把舊的類別擴充成新的類別, 可增刪資料成員與函數成員
          這概念很重要, 所以等一下我們用"動物與植物都是生物!"來詳細解釋。

    (4)多型 Polymorphism : 以基底類別(base class)的指標(C++的pointer)或參考(reference)操作衍生類別(derived class)的物件
          這比較難理解, 假設 Dog 和 Cat 都是 Animal(動物)這類別的子類別, 通常所有的 Animal 都會,
          在這, "" 是一個函數, 如果 myObj 被宣告或定義為一個 Animal 物件,
          那我們當然可以寫 myObj.叫( ); 表示 myObj 做""的動作(action),
    問題來了, 我設計程式之時並不知道 myObj 會是 Dog 還是 Cat,
          到時 myObj 可能是 Dog 也 可能是 Cat 甚至也可能是 其他類別!
    一個支援多型(Polymorphism)的電腦語言會根據 myObj 是 Dog 還是 Cat 去執行正確的叫( );
          如果 myObj 是 Dog, 那 myObj.叫( ); 用到的是 Dog 裡面的叫( );
          如果 myObj 是 Cat 當然用到的是 Cat 裡面的叫( );
      這在程式語言中的專業術語叫做動態綁定(dynamic binding; 動態繫結),
      意思是在執行階段(Run time)才決定啦。

      而這個動態綁定函數的專業術語就是多型(Polymorphism)啦。

      不太懂?
      沒關係 ! 因為這些議題已經超出我們課程的範圍, 該議題留給資工系的同學去傷腦筋即可 :-)

但是繼承(Inheritance) 或 擴充(extends)的概念很重要!
      所以我們現在用真實世界的概念來試著讓大家理解。
類別的繼承概念可以用我們小時候就學過的"界門綱目科屬種..."來作說明..
想起來了嗎?
動物與植物都是生物!
      所以動物與植物都繼承了生物的特性, 但又各自添加了不一樣的屬性(資料)與方法(動作行為)。
然後, 動物界又分為42門(Phylum), 不記得? 哈哈 .. 我也不記得:-)
人類是動物界脊索動物門, 哺乳綱, 靈長目, 人科, 人屬, 人種;
老師是人, 學生也是人,
也就是說老師與學生都是從"人"擴充(extends)來的!
  (雖然有一部電影叫做 "老師不是人")

      繼承(inherits)或擴充(extends)的概念非常重要,
例如已經有個類別叫做鬧鐘, 現在要設計豪華鬧鐘, 你該不會從 0 做起吧?
英文有句話很有名: Do NOT re-invent the wheel !
意思是不必再重新發明輪子, 已經有人發明了你就拿來用! (嚴格說來把輪子拿來用並不是繼承, 只是使用)
      既然已經有鬧鐘, 顯然豪華鬧鐘也是鬧鐘, 所以我們只要把鬧鐘拿來"擴充"並略加修改(modify)即可:
      class 豪華鬧鐘 extends 鬧鐘 {
          // ... 添加或蓋掉某些原有的屬性或方法(函數)
      } // class

也就是說, 只要有類似這種 YY 就是 GG 的關係(YY is a GG; 豪華鬧鐘 is a 鬧鐘),
或者該說 YY 是 GG 的一種特例, 例如 豪華鬧鐘 是 鬧鐘 的一種特例;
既然 YY is_a GG, 則 可以把 GG 拿來擴充(extends)為 YY, 那麼在 Java 語言就可以寫成:
      class YY extends GG {
          // 新增的屬性或欄位或說變數
          // 新增的函數或說方法, 包括要把原來 GG 已有的函數蓋掉(Override)的新函數
      }

      這就是所謂的繼承(inherits)或是擴充(extends)的概念, 是物件導向四大概念中很重要的概念, 有了這概念, 節省了程式設計師很多的時間!
如果還是很想了解更多關於物件導向概念的可以點這看我以前寫的講義"漫談 物件導向概念"

TOP        
     
     
Complex is better than complicated !?
                              Complex vs. Complicated (YouTube)
Python Interpreter (解譯器)內;
點這開REPL的job窗先打 python3 然後再打入:
import this

很神奇的 .. 你會在螢幕上看到 "Python 之禪" --
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!
>>>exit( )
美優於醜,明講好過暗諭。
簡潔為上,複雜次之,繁澀為下。
平舖優於層疊,勻散勝過稠密;力求簡明易讀。
特例難免但不可打破原則,務求純淨卻不可不切實際。
切勿默視錯誤,除非刻意如此。
在模擬兩可之間,拒絕猜測的誘惑。
總會有一種明顯又直覺的做法,那就是唯一的好方法。
雖說通常應該三思而後行,但馬上做勝於都不做。
難以解釋的實作方式,必定是爛點子。
容易解釋的實作方式,可能是好主意。
命名空間真是讚,讓我們善加利用。
===============================
**Python Namespace and Scope  
**Python3 命名空間和作用域
TOP        
     
 
亂數(Random number)的應用 亂數產生器(PRNG = Pseudo Random Number Generator)

* 你知道 電腦會撿土豆.. 電腦也有 AI 會玩公牛母牛Bulls&Cows(幾A幾B)遊戲喔:
      點這讓電腦猜你想的四位數字
(0123 到 9876, 數字不可以重複)
      (這是我用 JavaScript 寫的電腦猜人想的公牛母牛, 儘量把 JavaScript 的基本語法都用到了!)
* 蝦密? 要看那個 公牛母牛幾A幾B 網頁原始碼喔? 自己在該頁按滑鼠右鍵選檢視原始碼即可 !
    啥啦? 裡面用到 hello.txt 在哪喔?
      阿你就在檢視網頁原始碼時把 那檢視頁 的網址最後 ab.html 改為 hello.txt   (其實我有做連結讓你抓ㄟ)
      然後 按下 Enter 就偷回來了啊 :-)
    你把兩個檔案都存到你 PC Windows 上,
      然後在剛存檔的 ab.html 點兩下也可以把網頁叫起來喔, 沒騙你也沒藏私啦 !

* 這個電腦猜人想的公牛母牛Bulls&Cows幾A幾B遊戲就是典型的"亂數應用" + 簡單 AI (人工智慧)
* 亂數其實是亂中有序, 因為亂數是用公式計算出來的(根據你要的分佈模式), 所以稱"Pseudo"(假的)Random
* 注意 Pseudo 的 P 不發音, 點這到劍橋字典聽看看 Pseudo 的發音
* One of the most common PRNG is the linear congruential generator, which uses the recurrence:
你可以用 Google 查詢 PRNG + 12345 就可以找到 IBM 工程師發明, 廣泛用在 C/C++/Java 的亂數產生程式碼
      next = next * 1103515245 + 12345;

* 遊戲用的亂數採用均一分佈(Uniform Distribution) -- 機會均等才公平
    ** 但自然界很多現象屬於 常態分佈 (Normal Distribution)
    ** 請用 GoGLE 查詢 68 95 99.7 看看
    ** 假設全班 100人, 已知平均 70分, 標準差 10分;你是90分, 請問你至少贏了幾個人???

* 通常程式語言的亂數是 PRNG 產生的虛擬亂數, 就是說是"假的亂" !
      但 遊戲內卻希望亂數是"真的亂", 請問要怎麼做才能 "真的亂 " !?
    Hint: 可以利用 "時間" and/or 硬體的 GPIO 接腳信號等。
*** 這有83種語言人猜電腦想的公牛母牛(Bulls and Cows;幾 A 幾 B)遊戲的程式碼
*** 路人甲用 Python 寫的簡單 Bulls and Cows 公牛母牛遊戲(人猜電腦)(在 REPL.IT 網站)

    ** Python 語言在 2007, 2010, 和 2018 三度入選程式語言名人堂(Programming Language Hall of Fame)
 
給愛德琳   森林狂想曲   哆啦A夢   神隱少女   漂向北方   過客 何時 駱駝   菲兒鶴頂紅   阿冷 講真的 大叔   體面   有何不可     AoV     LoL     LoLWC     J (TPA)   TPS     網站架設教學
    大黃蜂 的飛行       Jessie is broken?   Jessie教英文     VoiceTube   1239   女生注意 男生注意 CatchHim 6ToB 7ToG     史嘉琳談LER回音法
👍 一定要用的GmailGoogle CalendarGoogle 雲端硬碟Google form表單:報名表問卷調查.. Google keep
👍 縮址的Goo.GLReURL.cc、以及可多人共同編輯的Google 文件(Word)、Google試算表(Excel)、簡報..
    總   結 (Summary)    
現在大家應該已經:
  * 知道電腦系統/Unix/Linux 以及 Python 和 Flask 大概是啥東東
  * 知道如何 Python 入門(跳到前面 REPL.IT 寫小遊戲)
  * 知道大概要如何利用 Python + Flask 做網站:(其實主要是做 Web Application)
      o 根據網址(URL)用 return 丟出(回應出)網頁(Web page), 三個範例: w.py, w2.py, 和 w3.py
      o 靜態網頁可以放 static/ 子目錄之下
      o 目錄 templates/ 這裡放會被 render_template( ) 用到的樣版檔   Jinja2 入門   Jinja2 Doc
也已經知道 要如何 執行 Python Script 程式碼:
  (a) 直接用終端機使用 Python Interpreter/commands 或 IDE(在 Linux/Unix/Windows ...等)
  (b) 瀏覽器 + 雲端 Python IDEhttps://REPL.IT/languages/python3
  (c) 瀏覽器 + Jupyter 在自己電腦
  (d) 瀏覽器 + Jupyter 在雲端開放的 IP/Port
  (e) 瀏覽器 + Jupyter 在雲端沒有開放的 IP/Port + SSH Tunneling
如果你夠認真那, 應該也學到了:
  。 學會 利用 ngrok 服務或 ServeO.Net 服務 ..
       把自己電腦的網站變成可以
https://某網址挖地道(Tunnel)連進來
  。 學會 Python 基本控制語句的語法如 if .. else 等 以及 基礎資料型別 data type
  。 知道 for / while LOOP 的用法-- 透過久久(九九)乘法
  。 還會用 def 函數名稱(參數): 來定義函數(函式; function)與使用函數
  。 也大略 知道 遞迴(Recursive)函數(函式; function)的神奇
  。 還知道有烏龜繪圖(Turtle Graphics)可以玩
  。 大略知道 class 類別 和 object 物件, 以及 Python Modules 模組 和 套件 Packages
  。 了解 亂數(Random number) 和 PRNG 以及它們的用途
  😏。。 發現 從公牛母牛(幾 A 幾 B)遊戲可以學會一些基本的 JavaScript 程式設計
  😡。 知道程式要防呆 -- 防止使用者呆呆的亂輸入 -- 例外處理(Exception handling)
  。 略懂 Python 虛擬環境 Virtual Env 的用法以及其必要性
  。 略懂物件導向程式設計(OOP)概念 Object Oriented Programming Concept
    。 Learn OOP using Python(Free udacity online course)
  。 略懂 Queue 佇列 / Stack 堆疊 以及堆疊溢位(堆疊滿出來; Stack Overflow)
  。。知道有問題可以到 stackoverflow 問:-) 其實 StackOverflow網站StackExchange 眾多網站之一
  。 知道有 VPython 可以玩   ( https://edutalk4.nctu.edu.tw/ )   https://vpython.org/
  。 知道有 IoTtalk 物聯網平台可以玩   https://demo.iottalk.tw/
  。 了解會員和流量就是金錢(許多併購案例的啟示)   請看Youtube 的評論(2016/10) 陳士駿:想被收..(2018/11)
  。 問問題也能賺錢可以證明其實點子(創意)遠比技術重要!       賈伯斯說過:創意, 偷就有了 !
  。 如果你有特殊才藝或才能, 可以在 HaHow好學校開課 就可以分潤賺錢; 或 到 Udemy.com 開課賺錢

那, 還該知道些啥呢 ?
  * templates 樣板檔案的 一些秘密 Flask Jinja MarkupSafe Requests Werkzeug(tool) Wrappers URL Routing urlLIB Python Library
  * 讓使用者在網頁輸入一些資料, 送到網站(伺服器)處理後, 丟回新的網頁
  * 搭配 AJAX: 類似上述, 但網站只丟回一些資料, 用 AJAX 技術換掉目前網頁中一部分內容
  * Flask 的家: flask.pocoo.org
  * Python + Flask with database SQLAlcehmy(47 min. Youtube)
  * Python Tutorial(W3Scol)   ;   Python 3 Tutorial   Python 基礎教程   老共寫的 Python 基础教程
  * Python 檔案讀寫   Python如何使用csv模組   Using Python csv
        open file mode: 'r' 讀取,'w' 寫入,'a'附加尾部,'x' 寫入不存在的檔案, 'b' 二進位檔案, 't' 文字檔案, '+' 可讀也可寫
  * UrlLib+BeautifulSoup 與網路爬蟲   也是網路爬蟲.爬蟲心得
  * Pandas熊貓可以分析資料     Pandas的家     Pandas之旅+Matplotlib     Pandas課程(9門課程免費)     Numpy 與 Pandas
  * 如果要用 Python 寫 GUI 的程式,可以點這看 Python GUI 設計影片教學(with Python Tkinter)
  * 要更詳盡 GUI 教學,可以點這看 Python GUI 詳細影片教學(也是 with Python Tkinter)(六小時)
  * Python GUI Tkinter 圖型式介面 Tkinter概述   3rdParty GUI   codeskulptor.org
  * How to Convert any Python File to .EXE 執行檔 (9分鐘 youtube)
  * 10 Python Tips and Tricks For Writing Better Code (39分鐘 youtube)
  Unix/Linux 愛好者, 也可以:
      下載 cmder 來用   ( cmder 的官方網站是 https://cmder.net/ )
  * Python PyGame.org
  * Python 入門教學影片(彭彭)     Python Basics Course(9門課程免費)     Python Programming course(Free)
  * https://code.visualstudio.com/ ( 2015/11/18 VSCode 開源Open Source )
  * Python Udemy_free_course   ( Python programming, Python and Flask by TheCodex on YouTube )
  * 21 種「知識性」教學素材資源網站     free.com.tw免費資源網路社群(賺GogLe廣告費過活)   PixLR.com線上編輯圖片
  * WeeBLY教學     WeeBLY Taiwan   健康很重要(tsaiwn.weeBLY.com)   自體免疫療法   本庶佑和艾利森獲2018諾貝爾獎 1006YTb 2014唐獎
  * 網頁(HTML/CSS/Javascript) / 多媒體 / 遊戲 相關教學點這 (cg.com.tw)
  * PowerPoint簡報技巧 (上課教:-)   YouTube   VoiceTube   TED   TEDxTaipei
  * Pinterest   Pinterest有啥用 Pinterest 好在哪裡? pinterest.com
  * 2019年網路賺錢方法 (大收集)
  * 比較4個用知識賺錢的線上課程教學平台
  **     百度知道   「分答」变成「在行一点」   「在行一点」     壹讀Read01 IT Read01   營養新知
  * 今日頭條 今日头条 每日頭條   今日新聞 nownews.com   新頭殼 NewTalk   Co-Co! 內容農場 cocoNet   FlipBoard flipboard  故事 如何封鎖內容農場 內農到底是瞎秘
  * 痞客邦 部落格     隨意窩Xuite     蕃薯藤     台灣最大非法網站 eyny.com   BT   bt  btc     台灣網站排名
  * AIoT 智慧音箱大賣  Amazon Echo GoogleHome 開箱體驗 Apple HomePod 遠傳 鴻海 小度 叮咚 小米 匪諜 盒子
  * 每天來點負能量(電子書)   Glossika有免費的 你不知道的英文發音(電子書)
  * 免費電子書學Server端Javascript Node.js   免費Python電子書   還有免費小說:-) Free Novel Robinson 漂流 讀後感 Robinson讀墨 武俠 GooglePlay   金庸
  * 🅶vm亞歷克羅斯:程式、跨領域、終身學習,是未來成功關鍵
  * 🆓A list of many many free eBooks.       🆓How to Open EPUB Files
這個網站裡收集了許多經典「英文版」電子書(PDF, ePUB, Kindle) ,包括「 孤雛淚」、「 雙城記」、「 咆哮山莊(艾蜜莉·勃朗特)」、「 魯賓遜漂流記」、「 格列佛遊記」、「 伊索寓言」、「 安徒生童話」、「 格林童話(德國格林兄弟)」、「 頑童流浪記馬克吐溫, 湯姆歷險記)」、「 傲慢與偏見(珍奧斯汀)」、「 簡·愛夏綠蒂·勃朗特)」、「 愛麗絲夢遊仙境(查爾斯·路特維奇·道奇森)」、「 金銀島(史蒂文生)」、「 白鯨記」、「 科學怪人」、「 聖誕頌歌(狄更斯)」、「 遠大前程(狄更斯)」、「 卡拉馬助夫兄弟們杜思妥也夫斯基; 罪與罰白痴)」、「 變形 (卡夫卡/存在主義)」、「 尤里西斯」 、 以及荷馬的伊利亞德」和「 奧德賽 希臘神話   希土之戰   Troy(電影) 谷阿莫賺很大   李子柒 Lz7 阿冷 馮提莫抖音神曲   喵喵喵 學唱歌 學唱歌 太用力
You are the -th visitors.                          
I saw a saw saw a saw when I was playing the seesaw.   三字經   VoiceTube voicetube
* 點這看如何選擇 VPS ?       * 還不太懂 HTML 的可以點這看我寫的超簡單 HTML 網頁教學(可搜尋 HTML + tsaiwn 找到)
    (建議用 DigitalOcean 或 Hostwinds.com 流量小可以先用免費的 AWS EC2)
* PuTTY official site to Download PuTTY
* PieTTY project official site   Download Pietty0400b14.zip

 

  整理 by 蔡文能 tsaiwn@cs.nctu.edu.tw     交大資工系     tsaiwn.weebly.com     LINE ID: tsaiwn     FB: fb.me/tsaiwn     幾個英文字讀音     GoGLE     TOP

ℋ 👍 想要查符號的 Unicode (UTF-8)   🏡 😂 🐞⌘ ♞ ❣ ©   Uber   AirBnB     Agoda Booking HotC   booking     Trivago Trivago流量 Trivago 廣告 新聞   Expedia
Blogger blogspot   MySpace   myspace   fbTSN   FB fb IG ig WhatsAPP   Snapchat   LINE   WeChat   PTT   Dcard   Meteor   膜拜01     TW網站     教育部開的站也會倒   均一
    Why學生   好學校hahow Rank   Udemy ud_Flask udemy Rank     OCW   ocwMIT   ocw台灣   OOPS Rank 奇幻   Coursera MOOCs 磨課師   OCWntu OCWnthu OCWnctu  
  思維宮殿記憶   5招讀書法   速學 速讀 速讀 有效讀 邏輯 睡飽 打屁 雪球速讀   問問題可賺錢 分答 知乎   興趣當飯 Blogger入門 鬼鬼 靠Gogle賺 領錢   蘭陵王 亂唱年賺一億 阿冷 Youtuber賺很大   冏星人
大壯不一樣 夢然好孤單 白安是甚麼   光年之外 洗腦想你   等你下課 我想有個家   小幸運   江山美人檸檬茶   Colors of the Wind 歌詞   Let it go 乎伊去   名人堂 Hall of Fame HallOFfame
  TOP  Find your FB ID: https://findmyfbid.com/ if you want to Find your Facebook ID   台灣啟示錄:搶菜攤丟江山內幕 柯P笑到翻過去 問世堅 摸魚兒 元好問 for fish 關雎