2015/08/24

新書發表:Python程式設計入門

2018.11.21更新:博碩出版社年末活動,推出本書的暢銷回饋版

2018.08.05更新:出版後過了三年,達到十一刷。歡迎任何改版建議、意見。

2017.11.11更新:出版後過了兩年六個月,居然達到刷。若有任何改版建議,還請留言。

2016.09.20更新:本書的投影片,可到此下載


嗨,各位好,我寫了一本Python程式語言的入門書,還請多多指教。

書名:Python程式設計入門
作者:我
出版社:博碩文化(書號PG21421
出版日期:2015年3月29日
頁數:544頁
ISBN:978-986-434-005-7
自從1980年代末以來,Python程式語言經過二十多年的耕耘,蓬勃發展,已成為世界當紅的主流開發語言之一,不論是開放原始碼界和商業公司,採用Python來開發軟體專案的例子比比皆是,更有許多成功的案例,而且不論是哪個領域,諸如網站開發、機器人控制、影像辨識、數學運算等,都可見其身影,足可知Python擁有非比尋常的的彈性與能力。

回想起過去的年代,當作者還是莘莘學子之時,學校開設的課程大都為C/C++/Java等語言,而在更早之前,作者的老師們學習的第一支程式語言,多半是Basic或Pascal,時至今日,許多學校與程式設計課程紛紛轉而使用Python作為教學語言,不僅是因為其語法簡潔易懂,適合作為初學者走入程式世界的第一支語言,也因為Python擁有豐富的功能與特色,即便將來欲走向其他領域或某特定的範疇,也都能使用Python,不必耗費時間學習另一支語言。

這是一本Python程式語言的入門書,將會詳細介紹Python的語法和語意,此部份屬於基本功夫,就好像學習英語時,需要學習單字、詞性、時態、文法等等,然後加以運用依據適當的結構寫出句子,也就是撰寫程式;但光如此並不足夠,我們還會介紹程式設計的各種概念,諸如函式、遞迴、閉包、物件等,並且會解說程式執行的抽象模型,透過該模型,思考寫下來的程式碼(死的)在執行時的動態交互作用(活的),如此一來,方能通透明白。

Python目前分為2.x版與3.x版兩個系列,彼此並非完全相容,換句話說,某些2.x版舊程式無法給3.x版執行,反之亦然;雖說3.x版較新較先進,但仍有很多人使用2.x版,仍有眾多的2.x版舊程式,所以本書將會同時兼顧,當有差異處時將會特別註明。以2.7、3.3、3.4版為主,這也是目前最新最普及的版本。

學習資訊科學相關知識時,免不了還是需要英文,因為許多第一手資料與文件,都只有英文,所以本書會放入英文詞彙,為了避免搞混,將會多次出現中英並呈,若原詞彙沒有適當且眾人公認的適當譯詞,或是直接使用原詞彙更顯得清楚明瞭時,將會直接使用原來的英文詞彙。

章節大綱:

第1章,介紹電腦的硬體與軟體,說明程式語言在其中扮演何種角色,簡述Python歷代版本的演進差異,然後下載並安裝Python實作,準備好開發環境,然後才能開始學習Python語言。

第2章,真正開始動手撰寫Python程式,從基本概念開始講起,介紹Python直譯器、何謂名稱與物件、指派的意義、各種運算式與述句、基本的資料型別、迴圈、函式、程式庫模組等。企圖以一章的篇幅介紹必備的基礎知識,有了這一章為底,接下來就可深入,繼續探究Python的各個面向。

第3章,介紹數值型別,包括整數、浮點數、複數、布林等等,以及可用的運算,介紹與數值相關的概念,譬如加總、平均、兩數的關係等等,數值是程式設計的基礎,說到底,電腦裡的所有資料終歸是一堆0與1、也就是數值罷了。之後會介紹具備特殊用處的十進位數和分數,以及整數的位元運算。

第4章,介紹Python的主力容器型別:序列,以及相關的迭代概念,這是一種一個接著一個、具備順序性的資料結構與操作方式,Python最重要的序列型別:序列,便是其中之一,許多議題與功能皆圍繞著串列打轉,譬如可迭代者與迭代器。除了串列外,還有元組與字串,並且介紹字串格式化。

第5章,介紹序列型別以外最重要的容器型別:字典,這是一種具備映射形式的的資料結構,每個元素都是所謂的鍵值配對,本章會介紹雜湊、集合等相關主題,最後簡介具有預設值和具有順序性的特殊字典。

第6章,函式是一門大學問,此章將從基礎逐步介紹函式的裡裡外外,包括如何定義、參數的傳遞、回傳值等基本知識,以及可被呼叫者和可視範圍等概念,並會以詳細的圖示解說何謂命名空間與環境,藉以了解遞迴、閉包、高階函式等進階主題,最後介紹直接由Python語法支援的產生器和延遲綁定的概念。

第7章,本章主題包括資料與編碼,重點放在檔案開啟與文字檔案,將會詳細解釋何謂文字編碼系統,期望能掃除此方面的疑惑,搞清楚底端的二進位資料只不過是一堆0與1(或說是一堆數字),須經過解釋後才具備意義;檔案是種抽象概念,不一定指硬碟裡的檔案,也可代表網路連線或其他資料讀寫來源。

第8章,認識的工具越多,便能根據狀況使用最適當的工具來解決問題,此章介紹串列和字典以外的其他容器型別,包括具名元組、雙向佇列、模組heapq、ChainMap、陣列等等。

第9章,函式實在太過重要,所以此章再談函式,再次深入探討,主題包括遞迴、尾呼叫、裝飾器、函數式程式設計、延遲執行等。

第10章,模組是管理大型軟體的重要利器,Python程式就是由模組所組成,本章介紹如何模組與套件的概念,如何建立模組,以及各種匯入模組並使用的語法,如何尋找、安裝、使用別人開發好的模組。

第11章,雖然至此章才介紹物件導向程式設計,但我們早已使用各種型別的物件撰寫程式;本章將介紹物件導向的主題,包括定義類別、封裝、繼承、重載、覆寫與多型,也會介紹多重繼承與後設類別。

第12章,現代程式語言碰見錯誤、無法執行、意外狀況時,都會提供一套異常處理機制來讓我們著手處理,本章介紹如何引發異常、該怎麼捕抓異常、如何自行定義異常類別。

第13章,學海無涯,此章將列出讀完本書後,接下來可進一步探索研究的主題。

附錄A,分類列出Python內建函式。

附錄B,概略列出Python 2.x與3.x版的差異。

附錄C,ASCII字元表,簡述ASCII和其在今時今日的用處,以及與其他文字編碼系統的關係。

附錄D,參考資料與學習資源,包括Python官方網站裡最常使用的頁面,學習Python的書籍著作與線上教材網站,程式設計的論壇、Q&A討論區、社群以及擷取最新資訊的新聞網站,並列出幾個不錯的練習題網站,藉以磨練寫程式與思考的能力。

原始碼:

書裡所有的原始程式碼檔案,都已上傳至GitHub,可自由下載,直接點按網頁上的「Download ZIP」,便會將所有檔案打包成zip壓縮檔下載,或自行使用git指令下載;章節內文中都會註明相對應的檔名,此外,某些練習題需要的輔助檔案,也一併放在此處。

勘誤表:

若發現任何錯誤,還請留言告知,謝謝。嚴重程度分為三等:小、中、大。

在日期2016.03.15之前的錯誤,已在第5刷修正。

日期:2015.04.13
嚴重程度:中
位置:第27頁,第1行。
原文:因為Python有可變物件(int、float、str)與不可變物件(list)之分
修正:因為Python有不可變物件(int、float、str)與可變物件(list)之分

日期:2015.04.16
嚴重程度:中
位置:第26頁,下方程式碼區塊的第2行、第3行、第6行、最後一行。

原文:>>> weight = 177          # 身高
修正:>>> height = 177          # 身高

原文:>>> height = 68           # 體重
修正:>>> weight = 68           # 體重

原文:>>> li4 = [name, weight, height, title, langs]
修正:>>> li4 = [name, height, weight, title, langs]

原文:['Frank', 185, 75, 'engineer', ['C', 'Python']]
修正:['Frank', 177, 75, 'engineer', ['C', 'Python']]

日期:2015.04.16
位置:第71頁,2.7節中的第2小節標題。把全形冒號改成半形冒號。
嚴重程度:小
原文:忘記冒號「
修正:忘記冒號「:

日期:2015.04.19
嚴重程度:小
位置:第54頁,小節「return述句」的第一段。
原文:但可回傳tuple物件,所以可把許多物件放在tuple裡,
修正:但可回傳容器物件,所以可把許多物件放在tuple或list裡,

日期:2015.04.19
位置:第49頁,小節「break述句與continue述句」的第1行。
嚴重程度:小
原文:使用迴圈述句(包括while與for)時,有時處理到某輪時,
修正:迴圈述句(包括while與for)處理到某輪

日期:2015.04.19
位置:第52頁,下方程式碼區塊的上面那一段。
嚴重程度:小
原文:函式定義完成後,便可使用它,
修正:函式定義完成後,

原文:函式呼叫屬於運算式
修正:函式呼叫在Python語法中屬於運算式

原文:在括號內傳入適當的參數
修正:在括號內傳入適當的參數

日期:2015.04.30
嚴重程度:中
位置:第57頁,第三個程式碼區塊的第5行,註解
原文:任何數的0次方都是0,包括0
修正:任何數的0次方都是1,包括0

日期:2015.04.30
位置:第59頁,最後一行。
嚴重程度:小
原文:呼叫boo()可得知某物件代表的真假值。
修正:呼叫bool()可得知某物件代表的真假值。

日期:2015.05.05
嚴重程度:小
位置:第46頁,倒數第三段、第一行。
原文:首輪的i是0
修正:首輪的i是1

日期:2015.05.05
嚴重程度:中
位置:第236頁,程式碼區塊的第5行
原文:return n * fact(n)
修正:return n * fact(n-1)

日期:2015.05.05
嚴重程度:中
位置:第263頁,第一個程式碼區塊最後一行的註解
原文:# 印出0、5、15
修正:# 印出0、5、10

日期:2015.05.05
嚴重程度:中
位置:第263頁,第二個程式碼區塊,第1行跟最後一行的註解

原文:x+n
修正:x*n

原文:# 印出0、5、15
修正:# 印出0、5、10

日期:2015.05.12
嚴重程度:中
位置:第36頁,第一個程式碼倒數第二行
原文:>>> li0 or li2
修正:>>> li1 or li2

日期:2015.06.05
位置:第22頁,倒數第二段的倒數第三行。
嚴重程度:小
原文:a最後會指向整數物件
修正:a最後會指向整數物件7

日期:2015.06.05
位置:第29頁,第一段的第二行,末尾。
嚴重程度:小
原文:所以必須如上述程式碼加個逗號
修正:所以必須加個逗號

日期:2015.06.06
嚴重程度:大
位置:第496頁,上面程式碼區塊
原文:
for i in range(num_agents):
    t = Thread(target=sell_tickets, args=(i, num_tickets, Lock()))
    t.start()
修正:
lock = Lock()
for i in range(num_agents):
    t = Thread(target=sell_tickets, args=(i, num_tickets, lock))
    t.start()

日期:2015.06.17
位置:第40頁,上面的程式碼區塊,倒數第三行。
嚴重程度:小
原文:# 注意i先成為1,然後才指派x[i]
修正:# 注意,i先被指派為1,然後x[i](x[1])才被指派為2

日期:2015.06.23
位置:第107頁,練習題3.3,第二行。
嚴重程度:小
原文:直到最後得到的和是3
修正:直到最後得到的和可被3整除

日期:2015.06.25
位置:第414頁,倒數第三行。

嚴重程度:小
原文:未免太陽春
修正:未免太陽春


日期:2015.06.25
位置:第7頁,第三段、倒數第二行。

嚴重程度:小
原文:PythonXY、Anaconda Python
修正:Python(X,Y)、Continuum Analytics的Anaconda、Enthought Canopy


日期:2015.06.26
嚴重程度:小
位置:第33頁,底下程式碼區塊,倒數第二行與第四行
原文:# a等於b嗎?
修正:# a不等於b嗎?

原文:# a等於b嗎?2.x版才有「<>」
修正:# a不等於b嗎?2.x版才有「<>」

日期:2015.06.29
嚴重程度:中
位置:第107頁,練習題3.7的圖3.1。
原文:
修正:

日期:2015.07.16
嚴重程度:小
位置:第126頁,上面的程式碼區塊,第12行的註解
原文:刪除奇數位置的元素
修正:刪除從索引值0開始、每隔2個位置的元素,直到最後

日期:2015.07.19
嚴重程度:小
位置:第360頁的程式碼區塊的註解
原文:# 0非偶數
修正:# 0不是奇數

原文:# n是不是奇數,等同於n-1是不是偶數
修正:# 「n是不是奇數」等同於「n-1是不是偶數」

原文:# n是不是偶數,等同於n-1是不是奇數
修正:# 「n是不是偶數」等同於「n-1是不是奇數」

日期:2015.07.21
嚴重程度:中
位置:第193頁,上面的程式碼區塊,倒數第七行
原文:{3, 4, 5, 6}
修正:{1, 3, 4, 5, 6}

日期:2015.07.26
嚴重程度:小
位置:第117頁,第一行。
原文:math、pi、circle
修正:math、pi、c、circle

日期:2015.07.26
嚴重程度:小
位置:第133頁,上面程式碼區塊的第二行,應加上底下的註解:
修正:# 注意li.copy(),3.x版的型別list才有方法copy

日期:2015.08.04
嚴重程度:小
位置:第284頁,上面程式碼區塊的第二行。
原文:fw = open('testw.txt', 'w')
修正:fout = open('testw.txt', 'w')

日期:2015.08.05
嚴重程度:小
位置:第43頁,下面程式碼區塊,倒數第五行。
原文:... elif
修正:>>> elif

日期:2015.08.12
嚴重程度:小
位置:第294頁,第一段第二行。
原文:Uncode
修正:Unicode

日期:2015.08.13
嚴重程度:小
位置:第407頁,第一行。
原文:formsts
修正:formats

日期:2015.08.18
嚴重程度:小
位置:第459頁,上面程式碼區塊第五行,可去掉「as e」,不影響該處程式。
原文:except ValueError as e:
修正:except ValueError:

日期:2015.08.18
嚴重程度:中
位置:第474頁,練習題12.1的程式碼區塊第三行。
原文:# raise Except('hello')
修正:# raise Exception('hello')

日期:2015.08.20
嚴重程度:小
位置:第464頁,程式碼12.2對應的檔名。
原文:(ch12_fact_exception_2.py)
修正:(ch12_fact_exception.py)

日期:2015.09.27
嚴重程度:中
位置:第432頁,程式碼倒數第二行。
原文:c.bar(c)         # 呼叫函式
修正:c.bar()          # 呼叫方法

日期:2015.10.21
嚴重程度:中
位置:第376頁,程式區塊、下半段、第一行。
原文:!even(n)
修正:not even(n)

日期:2015.10.31
嚴重程度:大
位置:第459頁,上方程式區塊第六行。
原文:'%s can not be less than 0'
修正:'%s is not a number or is less than 0'

日期:2015.11.16
位置:第174頁,第二段、第三行。
嚴重程度:小
原文:從鍵映到值
修正:從鍵映到值


日期:2016.02.07
嚴重程度:小
位置:第115頁,第一段、最後一行。
原文:使用內建函式instance
修正:使用內建函式isinstance

日期:2016.02.09
位置:第375頁,倒數第二段、最後一行。

嚴重程度:小
原文:函式一般
修正:函


日期:2016.02.12
嚴重程度:小
位置:第205頁,第二段、第二行。
原文:式陣列(associative container)
修正:式容器(associative container)

日期:2016.02.15
嚴重程度:大
位置:第250頁,上面的程式碼區塊
原文:for i in range(k):
修正:for i in range(len(items)):

位置:第250頁,第一段、第三行
原文:「for i in range(k):」
修正:「for i in range(len(items)):」

日期:2016.03.14
嚴重程度:小
位置:第v頁,目錄的1.2
說明:排版有誤,1.2 Python簡介的頁數「004」,應對齊最右邊

日期:2016.03.14
嚴重程度:小
位置:第xii頁,目錄的10.6
說明:排版有誤,目錄10.6的pip的頁數「418」,應對齊最右邊

在日期2016.03.15之前的錯誤,已在第5刷修正。 

日期:2016.03.16
嚴重程度:小
位置:第40頁,第一段、第三行
原文:並無法修改指向的int物件
修正:並無法修改指向的int物件

日期:2016.03.16
嚴重程度:小
位置:第57頁,最下面的程式碼區塊,第一行的註解
說明:「#」應對齊其他行的註解

日期:2016.03.16
嚴重程度:小
位置:第284頁,上面程式碼區塊的底下那一段、第二行
原文:但這麼做會一次載入檔案的全部內容
修正:但這麼做會載入檔案的全部內容

日期:2016.03.16
嚴重程度:小
位置:第316頁,倒數第三段、第一行
原文:否則甚少作低階的讀寫動作
修正:否則甚少需要自己作低階的讀寫動作

日期:2016.03.16
嚴重程度:小
位置:第317頁,中間編輯器列表的第一行;刪除多餘的空格
原文:Visual Studio裡  的Binary Editor
修正:Visual Studio裡的Binary Editor

日期:2016.04.01
嚴重程度:小
位置:第306頁,倒數第二段、第一行
原文:std.stderr
修正:sys.stderr

日期:2016.04.21
嚴重程度:小
位置:第347頁,8.2節、第一段、第二行
原文:double-dnded queue
修正:double-ended queue

日期:2016.07.07
嚴重程度:小
位置:第ix頁,6.5節的第2小節
原文:函式回傳函式
修正:函式回傳函式與nonlocal(3.x)

日期:2016.07.07
嚴重程度:小
位置:第35頁,上面程式區塊,第6行的註解
原文:# 注意
修正:# 注意,不同運算式的結果指向同一物件

日期:2016.07.07
嚴重程度:小
位置:第40頁,第3行
原文:a、b與c並無法修改指向的int物件
修正:a、b與c並無法修改指向的int物件

日期:2016.07.07
嚴重程度:中
位置:第47頁,程式碼2.2的第5行
原文:while i < 5:
修正:while i < n:

日期:2016.07.07
嚴重程度:小
位置:第98頁,上面程式區塊,第5行的註解
原文:取短名
修正:取短名

日期:2016.07.07
嚴重程度:小
位置:第115頁,第3行
原文:我們會稱呼某型別建立出來物件為「實體
修正:我們會稱呼某型別建立出來物件為「實體

日期:2016.07.07
嚴重程度:小
位置:第121頁,表4.3
說明:表格最後新增一列,內容為
操作動作:「sort(*, key=None, reverse=None)」
結果:「原地排序,3.x版才有」

日期:2016.07.07
嚴重程度:小
位置:第131頁,中間的程式區塊,第2行的註解
原文:# 找出'a'的索引值
修正:# 找出3的索引值

日期:2016.07.07
嚴重程度:中
位置:第132頁,第1行
原文:2.x版才有sort,建議改用內建函式sorted
修正:2.x版與3.x版都有sort,但參數稍有不同,與內建sorted同樣用法

日期:2016.07.07
嚴重程度:中
位置:第382頁,圖9.5
說明:圖9.5下面那一張圖不太正確,數字經過各個關卡後,可能會被過濾掉、可能會變化成其他數字(或別的物件),所以一開始若是「...3, 2, 1」,其他關卡不一定會看到。應把圖9.5換成底下這兩張圖。

首先是整批處理,range給出一整份資料,交給map。map處理完後,整批交給下個關卡。
若是延遲處理,range會陸續送出資料,經map處理後的資料已改變,如中間,但只處理部分。然後map把資料陸續送給filter,「5, 3, 2, 1, 1」過濾掉偶數後,filter送出的是「5, 3, 1, 1」。
日期:2016.07.07
嚴重程度:小
位置:第447頁,11.5之前的那一段,倒數第1行
原文:無法為類別A、B建立一致的MRO
修正:無法為類別A、B建立相容一致的MRO

日期:2016.07.12
嚴重程度:中
位置:第180頁,圖5.3
說明:應換成下圖。除了值,dict物件也要儲存鍵。注意,此僅為想像示意圖,非真實情況。
日期:2016.07.12
嚴重程度:中
位置:第181頁,圖5.4
說明:應換成下圖。set物件須儲存放進去的東西。注意,此僅為想像示意圖,非真實情況。
日期:2016.07.12
嚴重程度:小
位置:第272頁,小節「其他範圍」的倒數第二行
原文:產生器生成式
修正:產生器運算式

日期:2016.07.16
嚴重程度:小
位置:第255頁,圖6.22
說明:沒畫上垂直欄的攻擊黑線。請換成下圖:
日期:2016.07.19
嚴重程度:小
位置:第262頁,圖6.23,全域命名空間裡的名稱
原文:makeMultipliers
修正:make_multipliers

日期:2016.07.27
嚴重程度:小
位置:第231頁,程式碼區塊,第七行的註解
原文:# a、b、c都是在區域(函式)範圍內第一次指派,
修正:# a、b、d都是在區域(函式)範圍內第一次指派,

日期:2016.07.27
嚴重程度:小
位置:第231頁,程式碼區塊後第二行
原文:譬如li、a、b都屬於全域範圍內
修正:譬如前三行的li、a、b都屬於全域範圍內

日期:2017.07.30
嚴重程度:小
位置:第76頁,第二個程式碼區塊,倒數第二行與倒數第四行
原文:
倒數第四行:>>> x == y < z
倒數第二行:>>> x == y and y < z
修正:
倒數第四行:>>> x == y and y < z
倒數第二行:>>> x == y < z

日期:2017.08.26
嚴重程度:小
位置:第265頁,最後一段的開頭
原文:函式內只要使用了yield運算式,便成為產生器函式(generator function)、而非一般的函式,
修正:def述句內若有yield運算式,便成為產生器函式(generator function)的定義、而非一般的函式定義

日期:2017.09.09
嚴重程度:小
位置:第411頁,第9行
原文:那麼在 xyz 的 __init__.init
修正:那麼在 xyz 的 __init__.py

日期:2017.09.09
嚴重程度:中
位置:第412頁,表10.1的「乙」
原文:乙 可 可 不可 可
修正:乙 可 可 可 不可

日期:2017.09.15
嚴重程度:小
位置:第466頁,最後一行
原文:但不會印出foo
修正:但不會印出foo end

日期:2019.0917
嚴重程度:中
位置:第28頁,倒數第四行
原文:t1與t1指向同一個物件。
修正:t1與t0指向同一個物件。


472 comments:

  1. 請問書本內容會有像ARDUINO IDE軟體寫程式直接燒入硬體,用PYTHON上傳RASPBERRY PI執行程式嗎??謝謝~~

    ReplyDelete
    Replies
    1. 沒有。
      這本是Python程式語言的入門書,內容是函式、型別、名稱與物件、指派(assign)、類別、迭代、遞迴、資料結構、演算法、等等。
      還請看看本文列出的章節大綱。

      Delete
  2. Anonymous6/4/15 20:36

    這本書我大致上翻了一下...
    對於新手來說 還蠻好懂的

    ReplyDelete
  3. Anonymous13/4/15 13:08

    請教,第27頁"別名"內容的第一行"可變"與"不可變"物件是否有寫反?

    ReplyDelete
    Replies
    1. 啊,的確寫反了,非常抱歉。

      Delete
  4. Anonymous19/4/15 22:13

    完全沒有任何程式語言的經驗,怕看不懂。因為之前買了其他說明給沒經驗的,但是就是看不明白。

    ReplyDelete
    Replies
    1. 買電腦書之前,最好能站在書店裡,實際拿起書來翻翻看,認真看一會兒,看得懂才買。

      Delete
    2. 話說回來,不知道你之前買了哪些書。

      Delete
    3. Anonymous20/4/15 10:57

      在香港好難找編程書,不記得喇,哈哈

      Delete
    4. 在香港好難找編程書?
      咦,為什麼?書店進貨不夠多?要不然,網路買書應該很方便吧?

      希望拙作能對你有所幫助。

      Delete
    5. Anonymous20/4/15 11:42

      IT在香港從來都不重視,金融炒股書最多,先謝了

      Delete
    6. 台灣也是很多理財相關的書。

      不過現在網路買書應該很便利。

      Delete
    7. Anonymous20/4/15 12:10

      金石堂:)

      Delete
    8. Anonymous30/4/15 10:52

      第40頁 第一個程式碼區塊倒數第3行有誤
      >>>i , x[i] = 1 , 2 應改為 i = 1 , x[i] = 2

      Delete
    9. 沒有錯。
      i , x[i] = 1 , 2
      正是此處介紹的是「序列指派」。

      話說回來,改成
      i = 1 , x[i] = 2
      會出現錯誤訊息「SyntaxError: can't assign to literal」。

      Delete
    10. Anonymous30/4/15 11:13

      哎...搞懂了,謝謝指正

      Delete
  5. Anonymous30/4/15 14:28

    第57頁 第三個程式碼區塊倒數第6行註解有誤
    pow(333,0) , pow(0,0) #任何數的0次方都是0,包括0 => 應改為 #任何數的0次方都是1,包括0

    ReplyDelete
    Replies
    1. Anonymous30/4/15 15:00

      第59頁 最後一行 boo()可得知某物件代表的真假直
      一般性質的文句 boo() 少了l 是 bool() 函式

      Delete
    2. 第236頁 第一個程式碼區塊第五行遞迴(recursion) 呼叫自己 return n * fact(n) 沒有結束點
      是否要改為 return n * fact(n -1)

      Delete
    3. 感謝指正。

      很抱歉造成困擾。
      奇怪,原始碼檔裡是正確的,可是書內容卻錯了。

      Delete
    4. 第263頁
      第一個程式碼區塊最後一行註解有誤
      print(m(5)) # 0、5、15 => print(m(5)) # 0、5、10
      第二程式碼區塊因lambda運算式為 x+n 最後一行註解有誤
      print(m(5)) # 0、5、15 => print(m(5)) # 5、6、7

      Delete
    5. 謝謝。

      第二程式碼區塊的lambda運算式,應該改成「x*n」。
      所以註解也該改成「# 印出0、5、10」

      Delete
  6. Anonymous8/5/15 16:34

    請問有沒有教學投影片? 我打算當成上課教材.

    ReplyDelete
    Replies
    1. 沒有。

      如果您做好了,可以分享給大家嗎?嘻嘻:D

      Delete
  7. Anonymous12/5/15 22:38

    36頁
    >>> li0=[0,1,2]
    >>> li1=[]
    >>> li2=[None, False]
    >>> li0 or li2
    [0, 1, 2]

    ReplyDelete
    Replies
    1. 謝謝。

      應該把
      >>> li0 or li2
      改成
      >>> li1 or li2

      Delete
  8. Anonymous19/5/15 14:43

    124頁
    i若大於長度,會被視為長度
    j若大於長度,會被視為長度
    是否有誤?

    ReplyDelete
    Replies
    1. i若大於長度,會被視為長度
      所以 li[99: 3] 等同於 li[6:3],代表沒有東西,得到空串列 []

      j若大於長度,會被視為長度
      所以 li[3:99] 等同於 li[3:6] ,得到 [63, 74, 85]

      都正確。

      Delete
    2. Anonymous19/5/15 15:26

      謝謝,了解了!

      Delete
    3. 嗯,文字說明應可再加強,
      你覺得要怎麼描述比較好?

      Delete
    4. Anonymous25/5/15 09:50

      你程式碼的註解不夠,回覆的就說得很清楚

      Delete
  9. 葉大 可以請問一下 假如我今天做一個 "關閉"button
    我想點一下讓button的文字"關閉"變成"開啟"再點一下又變回"關閉"
    可以做到嗎?

    ReplyDelete
    Replies
    1. 呃,當然可以。

      Delete
    2. 請問葉大能給點方向嗎? 我的程式能力不是太好 ,周末在家試了整天都沒有試出來。

      Delete
    3. 你的程式碼?

      Delete
    4. # -*- coding: utf8 -*-
      from Tkinter import *

      win = Tk()
      a =[u'開啟',u'關閉']
      i=1
      def b():
      global i
      i=0
      return i
      win.geometry('800x600')
      win.title(u'寄信視窗')
      entry = Entry()
      entry2= Entry()
      entry3= Entry()
      Label(win, text=u"收件人").place(x =6, y =50)
      Label(win, text=u"主旨").place(x =10, y =80)
      Label(win, text=u"內容").place(x =10, y =110)
      entry.place(x =50, y =50,width=300)
      entry2.place(x =50, y =80,width=300)
      entry3.place(x =50, y =110,height=350,width=500)
      Button(win, text=a[i],command=b).pack(side=BOTTOM)
      Button(win,text='寄出').pack(side=BOTTOM)
      win.mainloop()

      Delete
    5. http://pastebin.com/pCKNFAPv

      # -*- coding: utf8 -*-
      from Tkinter import *

      win = Tk()
      a =[u'開啟',u'關閉']
      i=1
      def b():
      global i
      i= 1 if i == 0 else 0
      btn1.config(text= a[i])
      return i

      win.geometry('800x600')
      win.title(u'寄信視窗')
      entry = Entry()
      entry2= Entry()
      entry3= Entry()
      Label(win, text=u"收件人").place(x =6, y =50)
      Label(win, text=u"主旨").place(x =10, y =80)
      Label(win, text=u"內容").place(x =10, y =110)
      entry.place(x =50, y =50,width=300)
      entry2.place(x =50, y =80,width=300)
      entry3.place(x =50, y =110,height=350,width=500)
      btn1 = Button(win, text=a[i],command=b)
      btn1.pack(side=BOTTOM)
      Button(win,text='寄出').pack(side=BOTTOM)

      win.mainloop()

      Delete
    6. i= 1 if i == 0 else 0
      btn1.config(text= a[i])

      第一行不太懂
      第二行 是回傳裡面的值對嗎?

      Delete
    7. 第一行是條件運算式,如果i是0,結果是1,否則是0。詳見拙作第3.3節。

      第二行是修改設定,text是按鈕顯示的文字

      Delete
    8. 恩恩 好的 雖然手邊有圖書館借來的書 不過真的有看沒有懂 !!謝謝

      Delete
  10. Replies
    1. 謝謝。
      若發現任何錯誤,敬請留言告知。

      Delete
  11. Anonymous1/6/15 14:47

    請問練習題有解答嗎

    ReplyDelete
  12. 咳咳,我期待各位讀者能寫出來,發表出來,大家討論。
    :)

    ReplyDelete
  13. Anonymous1/6/15 16:52

    請問迴圈要怎麼學才好啊(從沒學過),我看內文的寫得還算好懂,但是一跳到練習題難度就翻了n倍:(

    ReplyDelete
    Replies
    1. 學習無途徑,只能多寫多看多練習。

      至於你覺得內文與練習題的難度差太多,嗯,這是我該改進的地方。

      有問題的話,可到各大論壇、Q&A網站、PTT的Python板發問,
      不過要小心,初學者詢問問題時,可能會:
      1. 對方是老鳥,覺得你問的問題太基本,叫你回家自己看書。
      2. 對方以為你是上來討回家作業的解答。

      至於,書中練習題的解答,嗯,有空的話,我會慢慢補上。orz

      Delete
  14. Anonymous4/6/15 17:13

    不好意思,我在p.252看到你用另一種方式算fibonacci數列,那個memo={0:0,1:1}是什麼 可以解釋一下嗎?感謝

    ReplyDelete
    Replies
    1. memo是個字典,記住以前算過的費氏數,鍵是n,值是fib(n)。
      一開始先給它初始設定,
      n為0時、fib(0)是0,
      n為1時、fib(1)是1。

      Delete
    2. Anonymous5/6/15 08:12

      那為何是{0:0,1:1}? 看不懂0:0,1:1的意思

      Delete
    3. Anonymous5/6/15 08:22

      看懂了,不好意思問了太粗淺的問題

      Delete
  15. Anonymous7/6/15 22:26

    請教一下,
    lock的第一個例子(售票員)中,程式碼這樣寫到底會製造幾個lock?

    ReplyDelete
    Replies
    1. 會產生10個。
      嗯,糟糕,這樣應該錯了。

      Delete
  16. Anonymous14/6/15 16:52

    您好, 稍微補充一下勘誤表

    1. 位置:第24頁,小節「return述句」的第一段。
    在第54頁

    2. 原文:所以必須如上述程式碼加個逗號
    在第29頁

    ReplyDelete
    Replies
    1. 修正書籍內容的勘誤表本身居然有錯誤,汗顏。
      謝謝。

      Delete
  17. hi:
    初學者想請教,您的書第40頁,指派的範例中:
    >>> x = [0,1]; i = 0
    >>> i, x[1] = 1,2 #注意i先成為1,然後才指派x[i]
    >>>x
    [0,2]

    您這段範例的i 先被指派為1然後又指派給x[i] 所以這個時候i =1 ,那為什麼結果出來是[0,2],.那1跑去那了...我直接認為是[1,2]..我那裡想錯了...可否指教一下,謝謝..

    (目前為止,您的書對我來說很容易讀,易懂,是本很好的書)

    ReplyDelete
    Replies
    1. 描述的不夠清楚。把註解改成
      # 注意,i先被指派為1,然後x[i](x[1])才被指派為2
      應該比較好。

      意思是說,執行i, x[i] = 1, 2時,
      會先做i = 1的部份,然後才做
      x[i] = 2的部份,此時i為1(之前是0),
      所以是執行x[1] = 2,
      於是x變成[0, 2]

      Delete
  18. Anonymous26/6/15 00:09

    我想請問,您寫這本書,有沒有一個估計,
    每天花多久時間,或進度多少頁,可以多久讀完?

    因為用工餘時間來讀,如果一天進度能有十頁,理想上是兩個月內,
    但實際上,到第二、三章以後,就算目標只有一天約兩小時十頁,
    應該也不是很容易?

    ReplyDelete
    Replies
    1. 每個人背景都不一樣,有人是學生、有人非本科系、有人是上班族、有人已學過C++/Java、有人只用過JavaScriptp、等等,無法估計。

      只有讀者才最了解自己的情況,能夠依據之前的學習經驗,自行預估並訂定目標。
      請先讀第2章,這是基本,也算是概觀全貌,讀完後,看看後面章節的標題,便可約略知道後面要介紹什麼東西。

      Delete
  19. Anonymous26/6/15 21:52

    請教,第33頁圖表倒數第三行>>> a != b a等於b嗎? 是否有誤?

    ReplyDelete
    Replies
    1. 謝謝。
      應把「等於」改成「不等於」

      Delete
  20. Anonymous28/6/15 21:18

    第 46頁,while迴圈,程式碼下面第一行,"首輪的 i 是0",但是程式碼中的第一行 i = 1

    ReplyDelete
  21. Anonymous28/6/15 21:43

    第 48頁,程式碼2.4,('AMY', 82, 90),但下方的 if 卻是 y>= 90,無法得到您敘述的,首輪的y是82

    ReplyDelete
    Replies
    1. Anonymous28/6/15 21:44

      抱歉,我好像搞錯意思了,這邊沒問題

      Delete
  22. Anonymous30/6/15 18:13

    第49頁,程式碼2.5:雙重迴圈最後一行 results += [x+' '+y] ,是否應該改成results += [x+y] ?

    ReplyDelete
    Replies
    1. [x+' '+y]

      ' '
      是為了插入一個空格

      Delete
  23. Anonymous8/7/15 10:40

    請問一下,第50頁 程式碼 2.9 要如何檢查加分表? 我用print(scores_new) 只出現1個答案: [99]

    謝謝指導

    ReplyDelete
    Replies
    1. 在整個程式碼的最後面,加上
      print(scores)
      print(scores_new)
      就會印出加分前與加分後的分數。

      Delete
    2. Anonymous8/7/15 10:47

      加問一下,程式 x = 90 是不是也要 x = [90] ?

      Delete
    3. 不是,x指向int物件,不是指向list物件

      Delete
  24. Anonymous8/7/15 11:25

    感謝葉大回答!! 我還想問說程式中間 第1個 if statement 是否需加入 "else:" x +=10 ,還有中間值 +10 以後的值是否也需要 assign 給 score_new呢 ??

    thanks!!

    ReplyDelete
    Replies
    1. 第1個if裡頭有continue,所以之後的程式碼其實等同於x<90的情況,
      若加上else的話,那麼需要改寫。同一種功能可以有多種寫法,此例是示範continue的作用。

      +10以後,根據題目的意思,需檢查是否x>=90做處理,然後再加入score_new

      Delete
    2. Anonymous8/7/15 11:40

      感謝葉大!

      Delete
  25. Anonymous10/7/15 17:05

    葉大 可以請問一下,練習題2.7 的 for loop: 可不可以註解一下 電腦運算過程,我想了半天還是搞不清楚! 謝
    for i in range(1,len(data)):
    if data[i] > result_x:
    if count > count_max:
    result_i_max = result_i
    result_x_max = result_x
    count_max = count
    result_i = i
    result_x = data[i]
    count = 1

    else:

    count += 1

    ReplyDelete
    Replies
    1. 加了。
      https://github.com/yehnan/python_book_yehnan/blob/master/ch02/ch02ex2.7_answer.py

      Delete
    2. Anonymous10/7/15 17:52

      謝謝了!

      Delete
    3. Anonymous14/7/15 12:59

      你好
      如果我把數列改成如下,
      data = [0, 1, 1, 2, 3, 4, 5, 5, 9, 9, 9, 23, 25, 25, 25, 25]
      最後出來的答案並不是25

      Delete
    4. 很抱歉,是我的bug,orz。
      應該把if count > count_max:的部份,拿到外面去。
      請看https://github.com/yehnan/python_book_yehnan/blob/master/ch02/ch02ex2.7_answer.py

      Delete
  26. 剛剛才發現,拙作登上天瓏六月份排行榜第10名,哇。

    ReplyDelete
  27. Anonymous14/7/15 16:33

    葉大請問:hwk 2.8之問題: 可以幫我修改嗎? 我測試了好久...

    #homework 2.8
    date1 = input('Please input the date: ' ).split(',')
    date2 = input('Please input the second date: ' ).split(',')
    date1 = [int(i) for i in date1 ]
    date2 = [int(i) for i in date2 ]



    from datetime import date
    First_date = date(date1)
    Last_date = date(date2)
    datedifferent = (abs(First_date-Last_date).days)

    print(datedifferent)

    ReplyDelete
    Replies
    1. 這題是希望你自己寫,計算並處理閏年,不過既然你找到適用的模組,那也可以。
      你的程式碼會有錯誤訊息吧,從訊息應可知道為何出錯。

      Delete
    2. Anonymous14/7/15 16:59

      這問題是探討2個日期,算出相差幾天,日期已串列表示

      Delete
  28. 你好, 範例程式 ch03ex3.4_answer.py
    第一個 def collatz(n):
    跑出來會有錯誤
    我改成 return collatz(n * 3 + 1)
    才會有結果

    ReplyDelete
  29. Anonymous16/7/15 21:55

    P126 #刪除奇數位置的元素,因該是偶數,但是我不清楚你奇數位置是指串列奇數嗎? 謝

    ReplyDelete
    Replies
    1. 的確語意不清,謝謝。
      改成

      # 刪除從索引值0開始、每隔2個位置的元素,直到最後

      應該比較好。

      Delete
  30. Anonymous17/7/15 22:38

    葉大你好:我好奇p141 是怎麼讀成[1,5,8,9]的? enumerate不是變成x = (I,J) 兩個元素嗎?

    ReplyDelete
    Replies
    1. 因為使用del刪除元素,所以真正會被該for迴圈處理的對象會是
      索引值0 元素1
      索引值1 元素2
      索引值2 元素6
      索引值3 元素9
      其中2跟6會被刪除。
      於是從[1,2,5,6,8,9]變成[1,5,8,9]。
      但正如書中所說,一邊迭代、一邊又做刪除,會導致奇怪的行為,最好不要這麼寫程式。

      Delete
  31. Anonymous19/7/15 01:20

    我猜, p360 那個判斷奇偶數的 code 一定是什麼地方有問題?
    要不然,就是我的腦細胞有問題了 ><

    ReplyDelete
    Replies
    1. code沒有問題。
      但註解有錯,請看剛剛加上的勘誤表。

      Delete
  32. Anonymous19/7/15 21:19

    葉大P155指定寬度為4個空格為何其數空格都不同?

    ReplyDelete
    Replies
    1. 所謂TAB,是根據某數字,例如8,把每一欄定位在8的倍數的位置上,也就是0、8、16、24、等等。
      假設游標在3,那麼插入TAB後應跑到8,依此類推。

      如果把TAB設為4,而某欄裡的字元超過4個,那麼就會跑到下一個位置。

      Delete
    2. 而呼叫expandtabs則是把TAB字元換成適當的空格字元。

      Delete
  33. Anonymous20/7/15 02:08

    葉大 在網路上搜尋Python的相關書籍,
    看到這邊討論如此的熱絡,
    相信書應該值得入手一本,
    感謝

    ReplyDelete
    Replies
    1. 咳咳,應該說是大家來找錯,呵呵。
      謝謝。

      Delete
  34. Anonymous21/7/15 21:12

    P179 #傳入內見函式Set,得到不重複元素的集合? set(li1) (可是好像列出重複元素集合? 1, 2 )

    ReplyDelete
    Replies
    1. 改成:
      # 傳入內建函式set,集合裡不會有重複的元素

      應該比較明白。

      Delete
  35. Anonymous22/7/15 21:08

    P193, s.pop() 應該還有{1,3,4,5,6}, 殊不知1到哪去了?

    ReplyDelete
  36. Anonymous26/7/15 20:27

    請問117頁右上角,"含有名稱math、pi、circle",是不是漏寫了c,因為第二行有提到"pi與c都是物件"?

    ReplyDelete
  37. Anonymous26/7/15 22:08

    葉大請問: P217 def_value 裡面的 return item[1], 請問 return item(參數) 似乎好像有預設值? 因為我用不同順序,但用同樣def_value 回傳順序好像一樣。

    ReplyDelete
    Replies
    1. 看不懂你的問題。
      p217沒有def_value。

      > 回傳順序好像一樣
      不管如何更動li的元素的順序,排序後當然會一樣。

      Delete
  38. Anonymous26/7/15 22:11

    請問我照第133頁的程式碼打,但是(第二行)會出現錯誤?

    ----> li3 = li.copy()
    AttributeError: 'list' object has no attribute 'copy'

    ReplyDelete
    Replies
    1. list的方法copy(),3.x版才有,其作用等同於list[:]。

      抱歉造成困擾。

      Delete
  39. Anonymous1/8/15 23:14

    請問,我裝了Python 3.4 在window系統, 打開是Python Shell,如何開啟 IDLE (GUI)

    ReplyDelete
    Replies
    1. 參照圖1.6,選單「IDLE (Python 3.4 GUI)」

      Delete
  40. Anonymous2/8/15 15:28

    怪,我的python灌完後只有shell視窗一個程式,無其他如圖1.6所市的選單出來,灌了三次都一樣, 我先找了IDLEX用,但我想知道為什麼? 有建義嗎?

    ReplyDelete
    Replies
    1. 你灌的Python實作是?到哪抓的?

      Delete
    2. Anonymous3/8/15 10:22

      從這下載灌的 https://www.python.org/downloads/ 選得是Python 3.4.3
      下載後的程式名是 Python 3.4.3 和書所述應是一樣的, 不解啊??

      Delete
    3. Anonymous3/8/15 10:23

      下載後的程式名是 Python-3.4.3

      Delete
    4. 的確是一樣的,我也不解。
      你的Windows是64位元版本嗎?

      Delete
    5. Anonymous3/8/15 11:09

      是的,是Windows7 64位元版本嗎, 32/64位元程式均可跑,有何建議我查什麼嗎?

      Delete
    6. 嗯,那試試64位元版的Python實作吧,
      https://www.python.org/ftp/python/3.4.3/python-3.4.3.amd64.msi

      Delete
    7. Anonymous3/8/15 11:54

      抱歉,我錯了,我在視窗左下角地球那只看到這個python, 執行後是shell,我沒檢查"所有程式",在所有程式內有2.7和3.4,都有IDE

      Delete
  41. Anonymous3/8/15 00:03

    菜鳥想請問一下,因為書是後來買的
    我之前是參照此網址教學的安裝軟體:http://djangogirlstaipei.herokuapp.com/tutorials/
    那麼還需要按照書中的開發環境等嗎?(會不會有衝突?)

    ReplyDelete
    Replies
    1. 只要你能照著1.6節所述,執行Python程式,Python shell執行一行一行程式或檔案,那就可以了。

      Delete
  42. Anonymous4/8/15 16:42

    P284. w寫入模式,應該是fout = open(.. 而不是 fw = open(....吧?

    ReplyDelete
  43. Anonymous4/8/15 21:32

    菜鳥發問
    p.36頁第二個黑框第四行的註解有點疑惑懇請解惑
    ******************
    li0 and li0[0]>25
    #光看li0就知道整個運算式的結果所以不會運算li0[0]>25
    可是37頁的運算子優先順序 >不是排在and之前嗎
    個人疑惑是 電腦檢查運算子 跟 short-circuit的順序好像沒提到
    因為照運算子修先順序,感覺li0[0]>25應該要運算到
    但用short-circuit 來思考下列情況 False and False or True 又不太一樣
    但我還是想知道電腦判斷執行的步驟是甚麼??
    然後在請問p.37頁表格 (expr...)是括號運算元嗎?還是括號不是運算元

    ReplyDelete
    Replies
    1. > 是在 and 之前,沒錯,
      所以 li0 and li0[0] > 25 等同於 li0 and (li0[0] > 25)
      而and運算子的運算順序是從左到右,而且有short-circuit行為,
      而li0是[],被視為False,就不會再去算li0[0] > 25。

      > 想知道電腦判斷執行的步驟是甚麼??
      最終都要去查詢Python文件,甚至去看Python實作的原始碼,
      https://docs.python.org/2.7/reference/expressions.html#and
      The expression x and y first evaluates x; if x is false, its value is returned; otherwise, y is evaluated and the resulting value is returned.

      Delete
    2. 括號() 是運算子,在Python裡有多種意義。

      Delete
  44. Anonymous5/8/15 15:56

    p.43第二段程式碼
    倒數第五行
    ...elif 應該是
    >>>elif 吧?

    ReplyDelete
  45. Anonymous8/8/15 11:52

    P316. 請問 with open('test', 'wb') as fout: 的 test 是 .txt files 嗎? 還是程式名稱? 感謝!

    ReplyDelete
  46. Anonymous8/8/15 13:04

    p.48.49的程式碼2.4與2.7
    有點搞混
    2.4的x是取list裡面的list的第一個物件
    同理我會認為2.7也一樣
    但2.7卻是直接取tuple裡面的的tuple
    是因為指派的方式不同嗎?

    ReplyDelete
    Replies
    1. 程式碼2.4,for迴圈首輪會從names_scores拿到('Amy', 82, 90),
      然後進行指派動作 x, y, z = ('Amy', 82, 90),所以x會是字串'Amy'。

      程式碼2.7,外面的for迴圈,首輪會從data拿到[33, 44, 55],所以x是[33, 44, 55]。

      Delete
  47. Anonymous9/8/15 10:29

    看到p85.有點好奇
    請問浮點數能用八進位,十六進位表示嗎
    因為我用bin(),hex()等發生錯誤才注意到這些函式只能轉換整數物件
    謝謝

    ReplyDelete
    Replies
    1. 現今絕大部分的CPU的浮點數格式,都採用IEEE-754,可分成三個部分,符號、指數、小數,詳情請見https://en.wikipedia.org/wiki/IEEE_floating_point。
      因此浮點數格式與我們熟知的整數二進位表示法不同。

      Delete
  48. Anonymous12/8/15 00:03

    p.286,第三段的結尾,"...資料不都是一個個位元組嗎。",這邊可能是問號結尾?
    p.294,第二行,"...以Uncode為核心",應該是Unicode
    p.296,下面的主題unicode_literals,"當想改寫3.x版...使其也適用於2.x版...",應該是2.x版要適用3.x版
    p.299,"...參數encoding...只該用於文字模式",應該是只能用於文字模式
    p.299,"...參數newline...只該用於文字模式",應該是只能用於文字模式

    以上是覺得怪怪的地方

    ReplyDelete
    Replies
    1. p.286,看似問句,但其實是肯定句,所以我沒加上問號。
      p.294,謝謝。
      p.296, 原文沒錯,但描述的不太清楚。意思是說,手上若有3.x版的Python程式,裡頭的字串都會是Unicode字串;若之後才想移植到2.x版,可加上unicode_literals,或可減輕移植難度。
      p.299,Python文件原文是「This should only be used in text mode.」,我覺得「只該」比較符合。

      Delete
    2. Anonymous12/8/15 19:44

      謝謝您的說明!

      Delete
  49. Anonymous13/8/15 21:00

    P407 First line 套件應為format ?

    ReplyDelete
  50. Anonymous18/8/15 21:28

    p.459
    第五行,except ValueError as e:
    這個as e這邊是多寫的嗎?
    因為後面的範例(p.464)有把e印出來,這邊似乎沒有用到

    ReplyDelete
    Replies
    1. 嗯,的確可刪掉。
      謝謝。

      Delete
  51. Anonymous18/8/15 21:44

    p.474,練習題12.1
    我知道加那行會跳到except,不加會執行else,但我想請問的是#raise Except('hello')
    後面的('hello')不管有沒有加都不會影響程式執行,不知道這個字串的用意,還有會出現在哪?
    謝謝

    ReplyDelete
    Replies
    1. 首先,Except('hello')應該改成Exception('hello')。
      'hello'不管有沒有都不會影響這個練習題的用意。

      但若把except: 改成 except ValueError:(或其他不相干的異常),
      那麼因為異常會被直譯器補抓並印出,就會印出'hello'字串,便於識別。

      Delete
    2. Anonymous20/8/15 22:18

      我有翻回去閱讀前面的內容,p.464

      1. github的程式碼跟書上印的不一樣,多了17-19行,書上沒有。

      2. 不論是書上或github的程式碼,都無法成功得到p.465的input n:qwert的錯誤指令。
      會直接跳出unknown error,而不是書上寫的"invalid literal ...",但應該是要跳p.464的"Argument must be type int"?
      我在想是不是跟p.464,while迴圈裡的f=fact(int(s))已經預設是int有關?

      Delete
    3. Anonymous20/8/15 22:32

      您回覆的"首先,Except('hello')應該改成Exception('hello')。"
      所以p.474的練習題上面印錯了對嗎?我應該改成你寫的Exception,才是python內建的異常型別

      Delete
    4. Anonymous20/8/15 22:38

      我翻到前面複習

      p.464的程式碼並不能得到p.474的執行,這一句會有問題:
      input n:qwert,實際上得到的結果會是"unknow error",而不是講義的"invalid literal for int() with base 10"
      但是訊息要應該也是p.464的"Argument must be type int",這邊看不太懂...

      問題發生的原因不知道是不是while迴圈裡的f=fact(int(s)),已經預設是int?

      另外github的程式碼多了17-19行,但不影響,只是跟講義長的不同。

      Delete
    5. Anonymous20/8/15 22:39

      上面打太快,應該是"p.464的程式碼並不能得到p.465的執行結果"

      Delete
    6. > 所以p.474的練習題上面印錯了對嗎?
      錯了。

      > 我應該改成你寫的Exception,才是python內建的異常型別
      是的。
      寫「Except」其實會造成NameError。

      Delete
    7. > p.464 1. github的程式碼跟書上印的不一樣,多了17-19行,書上沒有。
      github上的檔案,是加上程式碼12.2後的內文描述,變得更好的版本。

      > 2. 不論是書上或github的程式碼,都無法成功得到p.465的input n:qwert的錯誤指令。
      你應該是用Python 2.x版,而且沒有把程式碼裡的input改成raw_input。
      當使用Python 2.x版的input時,input會把輸入的字串當做Python程式碼去執行,而當輸入'qwert'時,會引發NameError(因為沒有這個名稱),而在這支程式裡,會被最後一個except子句補抓,於是印出'Error: unknown error'。

      當使用2.x版時,請改用raw_input。3.x版則使用input。

      Delete
    8. > 而不是講義的"invalid literal for int() with base 10"
      在try裡,各個地方都可能引發異常。input本身可能、int也可能、fact也可能。

      當呼叫input(3.x版)並輸入qwert後,s會是'qwert',然後s傳入int,int無法解析,於是引發異常,印出"invalid literal for int() with base 10"。

      Delete
    9. 抱歉,有錯誤。
      >> p.464 1. github的程式碼跟書上印的不一樣,多了17-19行,書上沒有。
      > github上的檔案,是加上程式碼12.2後的內文描述,變得更好的版本。
      正確地說,書中程式碼12.2應該對應到檔案ch12_fact_exception.py,而ch12_fact_exception_2.py則是稍加改進後的版本。

      Delete
    10. Anonymous20/8/15 23:51

      謝謝你的仔細回覆,我搞懂了!
      我用2版沒錯,忘記修正了。

      Delete
    11. Anonymous9/9/15 21:32

      針對您回覆的"但若把except: 改成 except ValueError:(或其他不相干的異常),
      那麼因為異常會被直譯器補抓並印出,就會印出'hello'字串,便於識別。"

      請問是我哪裡搞錯了嗎?無法順利執行,code如下:

      try:
      print "try"
      raise Exception("hello")
      except ValueError:
      print "except"
      else:
      print "else"
      finally:
      print "finally"

      Delete
    12. 可以啊,輸出如下:
      try
      finally
      Traceback (most recent call last):
      File "a.py", line 5, in
      raise Exception("hello")
      Exception: hello

      其中印出'hello'了。

      Delete
    13. Anonymous9/9/15 21:47

      啊...我以為hello會print出來的,原來是在error的訊息裡,瞭解了,謝謝

      Delete
  52. Anonymous18/8/15 21:55

    P.475,練習題12.10
    在finally裡執行continue語句,跳出錯誤訊息
    "SyntaxError: 'continue' not supported inside 'finally' clause"
    但我以為應該是他會跳過time.sleep(10)
    連續印出ACACAC?

    ReplyDelete
    Replies
    1. 沒錯,跳出錯誤訊息是正確的行為。
      根據Python官方文件https://docs.python.org/3.4/reference/compound_stmts.html#the-try-statement,
      A continue statement is illegal in the finally clause. (The reason is a problem with the current implementation — this restriction may be lifted in the future).

      finally裡不能有continue。

      本書內文沒講這點,放在練習題了。

      Delete
  53. Anonymous20/8/15 22:44

    奇怪,我發出去的訊息好像被吃掉了,如果有重複出現請版主刪除。

    重打一遍問題:

    p.464的程式碼無法得到p.474的執行結果,
    輸入unput n:qwert會得到unknow error,而不是講義上的"invalid literal..."
    但是就算要出現應該也是p.464的"Argument must be type int",不知道講義的結果是怎麼來的?

    猜測是while迴圈裡的f = fact(int(s))造成的問題?

    ReplyDelete
    Replies
    1. 因為Blogger錯認你的問題為垃圾留言,已修正。
      已於前回答你的問題。

      > 猜測是while迴圈裡的f = fact(int(s))造成的問題
      有疑問的話,可自行改寫程式,自行嘗試,找出引發"invalid literal for int() with base 10"來自何處。

      Delete
  54. 練習題3.2
    return int((n - 130) / 70.0 * 15.0 + 60)
    是否應修改成這樣?
    return int((n - 130) / 70.0 * 25.0 + 60)

    ReplyDelete
  55. 練習題3.6
    若測試的數字為132或423會輸出False
    原因為此兩數相減為99
    99頭尾對掉還是99
    我的解決方案如下:
    ndef = abs(nabc - ncba)
    if len(str(ndef))==2:
    ndef*=10
    若相差的結果為十位數,先乘以10再做頭尾對掉
    即可輸出True

    新手入門謝謝指教

    ReplyDelete
    Replies
    1. 此題目的條件是「百位數與個位數必須相差2以上」,132與423不符合。

      你說的可行,但加入該規則的話,會增加難度,變成另一個題目。

      Delete
    2. 漏看一句XD感謝指教

      Delete
  56. This comment has been removed by the author.

    ReplyDelete
  57. P.432的程式碼最後一個c.bar(c)應該改成MyClass.bar(c)或c.bar(),不然會出現錯誤
    在書上提到int的資料型態是type,function的資料型態是types.function,但我打type(function)顯示的是type而非types.function?
    BTW,很喜歡您的書,感覺是目前Python最好的中文書,希望有再版能把一些明顯的錯誤修正以利收藏

    ReplyDelete
    Replies
    1. > P.432的錯
      謝謝。

      > 但我打type(function)顯示的是type而非types.function?
      你的「function」是什麼?你指的是書中哪一頁?

      > 再版
      請向出版社建議。

      Delete
    2. This comment has been removed by the author.

      Delete
    3. P113-114頁的主題:型別也是物件
      int, float, complex我輸出是 class 'int', class 'float', class 'complex'
      type(sq)我輸出是class 'function' 而非types.FunctionType
      不過我剛才恍然大悟,是不是這是2.x版的,因為type跟class有分開?

      Delete
    4. 輸出class 'int'的話,應是3.x版。

      p113頁的示範程式碼:
      >>> type(sq); type(math)



      請看p114頁的示範程式碼:
      >>> import types
      >>> type(sq) is types.FunctionType
      True

      於是可知type(sq)與types.FunctionType,事實上指向同一個型別物件

      Delete
    5. > BTW,很喜歡您的書,感覺是目前Python最好的中文書
      承蒙謬贊,謝謝。

      Delete
  58. Anonymous30/9/15 07:43

    請問有電子書版嗎?人在美國,博客來寄海外運費真是不低......

    ReplyDelete
  59. 請問有電子書版嗎?人在美國,博客來寄海外運費真是不低......

    ReplyDelete
    Replies
    1. 沒有耶。
      要向出版社建議。

      Delete
  60. p376的程式碼
    def odd(n): return !even(n) !會的地方會報錯" invalid syntax"
    不太清楚這裡!的用法

    ReplyDelete
    Replies
    1. 抱歉,寫錯了。
      ! 要改成 not


      ! 是C/C++/Java的運算子。

      Delete
  61. P432最後一行
    c.bar(c)執行錯誤
    應該為MyClass.bar(c)

    ReplyDelete
    Replies
    1. 是寫錯了,
      但正確的是
      >>> c.bar() # 呼叫方法

      Delete
    2. This comment has been removed by the author.

      Delete
    3. a and b
      這是and,看到a是[],代表「假」,所以不必再看b;運算結果應為False,但Python會直接給出a(也就是[],也代表假)。

      b and a,b是1代表真,所以繼續看a,a是[]代表假,所以運算結果為假,直接給出[]。

      a or b,看到a是[],因為是or,還不能決定整個運算式的結果,繼續看b,b是1為真,所以結果為真,但Python會直接拿b的值當做結果,所以是1。

      b or a,看到b是1(為真),因為是or,不必再看a。所以結果為真,直接給出1。

      c是0吧?
      運用同樣的道理,便可解釋。

      Delete
  62. 不好意思初學Python
    想請教一下
    第36頁 and or 用法
    假設
    a=[]
    b=1
    c=0
    print(a and b,b and a,a or b,b or a)
    print(a and c,c and a,a or c,c or a)

    得出結果如下是該如何解釋呢
    >>>
    [] [] 1 1
    [] 0 0 []

    ReplyDelete
    Replies
    1. a and b and c and d and e
      會從左邊開始,依序看a、b、c...的值,若為真就繼續看下一個,若代表假的值,就停止,假設停在d,那麼結果就是d;若a b c d全部為真,那麼結果就是最後e的值。

      a or b or c or d or e
      會從左邊開始,依序看a、b、c...的值,若為真就停止,假設停在d,那麼結果就是d;
      若a b c d皆為假,那麼結果就是最後的e的值。

      Delete
    2. 非常感謝~
      獲益良多的一本書

      Delete
  63. p485頁 程式碼12.1
    無法正確顯示輸入非int的結果
    若輸入q
    輸出'q can not be less than 0'
    而不是'q is not an integer'

    ReplyDelete
    Replies
    1. 嗯,輸入q所引發的異常是int()丟擲的ValueError,
      而fact()也會丟擲異常ValueError,
      但兩者的原因不相同,於是導致錯誤訊息不匹配。

      謝謝。

      Delete
  64. 當直接輸入from fractions import Fraction時
    回傳
    Traceback (most recent call last):
    File "", line 1, in
    from fractions import Fraction
    File "C:\Users\Chen\Desktop\python\fractions.py", line 1, in
    from fractions import Fraction
    ImportError: cannot import name 'Fraction'
    是怎麼回事呢

    ReplyDelete
    Replies
    1. 把fractions.py的檔名改掉。

      Delete
    2. 因為你的原始碼檔名,與內建模組名,起衝突。

      Delete
  65. 請問這本書有打算在google play上架嗎?

    ReplyDelete
    Replies
    1. 這個要詢問、建議出版社(博碩)喔。

      Delete
  66. 不好意思
    請問一下'list'的問題
    在133頁提到淺複製有別名問題
    但是還是有些疑惑
    所以我試了一下

    li=[[100,50],2,3,4,5]
    li2=li
    li3=li[:]
    li4=li.copy()
    li5=list(li)

    li[0][0]=0
    li[1]=0
    print(li,li2,li3,li4,li5)
    >>>>>>>
    [[0, 50], 0, 3, 4, 5] [[0, 50], 0, 3, 4, 5] [[0, 50], 2, 3, 4, 5] [[0, 50], 2, 3, 4, 5] [[0, 50], 2, 3, 4, 5]

    為什麼會有這樣的差別呢?

    ReplyDelete
    Replies
    1. 什麼差別?

      li2與li指向同一個物件。別名。
      li3,li4,li5都是淺複製,分別指向不同的物件,但其第1、2、3、4個元素,一開始指向與li相同的物件(整數物件2 3 4 5)。
      但其第0個元素,都是指向同一個可變物件[100,50]。

      所以,li[0][0] = 0之後,[100,50]變為[0, 50]。
      所以,li[1]=0之後,只有li與li2受影響。li3的[1]仍指向整數物件2。

      Delete
  67. 請問199頁 程式碼5.4 那邊
    請問當中 if x & 0x1:
    sub.add(li[i])
    x>>1

    這裡可以解釋一下 if x & 0x1 的判斷 與x>>1 的意思嗎?

    ReplyDelete
    Replies
    1. x & 0x1 是判斷整數x的最低有效位元是否為1,
      x >> 1 是讓x的位元向右移。
      放在迴圈裡的話,就會先檢查x的第0個位元、然後檢查x的第1個位元、等等。

      程式碼5.4以0到7(8個整數)的二進位表示法,來判斷某元素要不要放進子集合。

      假設s = {'a', 'b', 'c'},傳入powerset(),
      x首先會是0,請看表5.3,x的三個位元都是0,所以在程式碼5.4裡面那一個for迴圈,因為x&0x1都會是0(False),因此不會執行sub.add(li[i]),也就是三個元素都不會放進子集合,因此冪集合的第0個子集合是空集合{}。

      x然後會是1,請看表5.3,最0個位元是1,所以for迴圈會把'c'放進子集合。
      依此類推,
      若x是5,那麼會把'a'與'c'放進子集和。

      如此一來,便能產生出冪集合。

      Delete
  68. Anonymous15/2/16 16:05

    此書我去書局看過了, 它已經初版四刷了, 是否能考慮從初版裡修正之呢?
    學習是永無止境的, 造福人群, 謝謝!

    ReplyDelete
    Replies
    1. 咦,居然已經四刷了,我怎麼都不知道。
      照理說,出版社應該通知我,看看有無需要訂正之處。

      讓我跟編輯聯絡看看。

      Delete
  69. Anonymous15/2/16 19:05

    作者您好;在程式碼6.6(P.249)中,我最後補上print(perm([0,1,2],2)),而互動交談模式則跳出[(0,1),(1,0)],跟預期書上的答案不同?感謝回答!

    ReplyDelete
    Replies
    1. 哇,好大的bug,在此致上歉意。

      請把
      for i in range(k):
      改成
      for i in range(len(items)):

      Delete