這樣寫好嗎?

閱讀時間約 8 分鐘
製作fractal圖案,由匈牙利生物學家Aristid Lindenmayer所開發的L-system是個好用的工具。在研究L-system時,在一個網站(https://understanding-recursion.readthedocs.io/en/latest/15%20L-System.html)中看到了一段程式碼,一段乍看之下覺得挺詭異,懷疑是不是寫錯,但搞清楚之後卻拍案叫絕,冷靜下來後卻覺得這樣寫不怎麼好的程式碼。在研究這段程式碼的過程中,也才發現以前在讀官網的文件時,有點自以為是的忽略掉了一些東西,更激起是不是該再來從頭讀一讀官網文件的念頭。
那段程式碼要做的事情其實很單純,就是要把一串字串中的某些字元,代換成另一些字元。一個簡單的例子是:把一個字串裡頭的a、b、c分別以x、y、z來取代,其他的字元則不變。所以如果原本的字串是a-b+c*d,取代過後就會變成x-y+z*d。根據那個網站的寫法,程式會長這樣:
rule = {'a': 'x', 'b': 'y', 'c': 'z'}
string = 'a-b+c*d'
ans = ''.join([rule.get(char) or char for char in string])
讓人覺得詭異的部分是
rule.get(char) or char
邏輯運算子「or」得到的結果不是True就是False,怎麼可能最後可以得到字串?可是程式實際執行的結果,還真的可以得到正確答案。這究竟是怎麼一回事?
在網路上看了幾篇相關討論的文章,總算搞清楚了,不過要解釋的話,就得話說從頭了。
在進行邏輯判斷時,會有true和false兩種可能的結果。一般會用T或1來表示true;F或0來表示false。而在說明and、or、not、xor等邏輯運算子時,通常都會提到真值表。以or來說,真值表長這樣子:
A  B    A or B
F  F    F
F  T    T
T  F    T
T  T    T
稍微觀察一下就會發現,對於or來說,只要A、B中有任何一個是T,那最後的結果就是T。所以當A是T的時候,就已經可以確定結果是T了,後面的B就不用管它了。Python的官網文件中(Library Reference/Built-in Types/Boolean Operations),特別註明and、or是short-circuit operator,指的就是這種只要做到可以確定結果了,後面的部分就不做了的做法。就好像三戰兩勝制的比賽,比完前兩場,已經有一方贏了兩場,那就不用再比第三場了,因為勝負已定。這可是完全違反孔老夫子「行不由徑」的訓示。不過話又說回來,孔老夫子不會寫程式,不然應該也會同意這樣的做法。
因為and、or是short-circuit operator,所以它們的運算結果就不需要像真值表那樣,鉅細靡遺地列出所有狀況,而可以加以簡化。以or 來說,A or B的結果,可以寫成這樣的一條運算規則
if A is false, then B, else A
以前讀文件看到這條規則的時候並沒有太在意,覺得反正就是換湯不換藥,沒什麼特別的。沒想到,貓膩就藏在其中,一切的一切,都可以在這裡找到答案。不過,要想找出貓膩在哪,還得先瞭解一些東西。
前面提到過,false、true也可以用0、1來表示。有些程式語言比較大器,把除了0之外的整數,都當作true。至於Python呢,就更大開大闔了,把看起來和0會物以類聚的東西,例如None,都當作false,而其他的一切一切,都當作是true。在文件(Library Reference/Built-in Types)中,還特別有個小節「True Value Testing」專門在談這件事,並列出會被當成false的內建物件。
搞清楚Python對false、true的態度之後,再回頭看看那條規則就會發現,A or B所得到的,可能是A或B,而不非得是一直以來認為的true或false而已。所以啊,那條規則其實不是簡化版的真值表,而是在short-circuit操作下,or的廣義化運算規則。
萬事俱備了,可以來看看,為什麼那段讓人覺得詭異的程式,居然可以得到正確的結果。
先來看看rule.get(char)會得到什麼。
要從dictionary中取出某個key對應的value,可以直接指定key。例如rule['a']會得到'x',但如果指定的key不存在,則會傳回KeyError。另一種寫法是使用get()方法。例如rule.get('a')一樣會得到'x',不過,如果key不存在,傳回來的會是None。
這樣就很清楚了。當char不在rule裡頭時,rule.get(char)會得到None,而None會被視為false。根據or的那條廣義化運算規則,當A是false時,A or B會得到B,也就是說rule.get(char) or char會得到char。反之,當char在rule裡頭時,rule.get(char)會得到對應的value,而對於所有不是false的東西,都是true。根據or的廣義化運算規則,當A是true時,A or B會得到A,也就是說 rule.get(char) or char會得到rule中對應於char的字元。
九彎十八拐,繞了好大一圈,總算搞清楚這看起來很有學問的寫法了。不過一開始相遇時的驚艷,卻在激情過後逐漸轉為懷疑:這樣寫好嗎?寫成
''.join([rule[char] if char in rule else char for char in string])
不是更直接了當清楚易懂嗎?難怪網路上有人說用or的這種寫法,不是Pythonic的寫法。
除了讓人覺得不夠清楚易懂外,用or的這種寫法,其實是有點危險的,有可能會造成很難察覺的問題。
有天晚上剛躺上床準備去找老周泡茶聊天時,突然想到,如果rule裡頭某個key的value,是個會被當成是false的物件時,會發生什麼事?還能得到正確結果嗎?和老周泡茶時聊到這話題,他老人家一副莫測高深不置可否的樣子,只說:「夢裡尋他千百度,驀然回首……」,居然打起啞謎來了。其實啊,想也知道他不知道答案,畢竟他的專長領域是睡眠,不是程式。不過,與其在夢裡想他千百遍,不如實際電腦跑一遍。不動手,再大的夢想,都是空想。
實際測試的結果:真的會出問題!如果把rule裡頭'a'這個key的value改成整數0或空字串'',那'a'會被保留,不會被置換。使用or的寫法,雖然讓人覺得挺炫的,但還是少用為妙。
在葉李華的科科網(http://yehleehwa.net/index.htm)中,有篇「樞紐與轉捩點──小兵立大功的銀河帝國系列」(http://yehleehwa.net/empire.htm),提到關於科幻大師艾西莫夫的一則小故事:
一九五○年初,剛過完三十歲生日,他終於出版了生平第一本書──長篇科幻小說《蒼穹一粟》。這件事帶給他極大的鼓勵,為其職業作家生涯埋下重要的伏筆。
根據艾西莫夫自己的說法,這本書出版後,他正式將自己視為作家。因此,在撰寫下一部長篇小說的時候,他刻意捨棄之前的筆法,嘗試將一字一句寫得足夠有文學味。好在剛寫完兩篇樣章,一位編輯(後來成為他的好友)及時給了他當頭棒喝。
那位編輯說:「你可知道,『第二天早上太陽出來了』這句話,海明威會怎麼寫?」
艾西莫夫承認只聽說過海明威,但從未讀過他的小說。於是那位編輯宣佈答案:「第二天早上太陽出來了。」
這段僅僅十秒鐘的對話,給了艾西莫夫絕大的啟示。其後整整四十年,他始終堅守這個原則,盡量將文句寫得通俗易懂,從不刻意賣弄辭藻或文采(搞笑時例外)。不知不覺間,這種風格便成了他的金字招牌。
「第二天早上太陽出來了」,這寫法還真是有The Zen of Python的味道。原來,寫作跟寫程式,骨子裡還真是挺像的啊!
為什麼會看到廣告
13會員
92內容數
寫點東西自娛娛人
留言0
查看全部
發表第一個留言支持創作者!
ysf的沙龍 的其他內容
關於lambda function的二三事
閱讀時間約 13 分鐘
幫醜程式整型
閱讀時間約 6 分鐘
學程式數學要很好嗎?
閱讀時間約 5 分鐘
龜蛛賽跑
閱讀時間約 5 分鐘
迷人的fractal圖案
閱讀時間約 4 分鐘
非戰之罪
閱讀時間約 5 分鐘
你可能也想看
學測國文作文這樣寫!全國作文特優台大生的準備心法(一)學測作文占學測國文總成績之50%,進而依此計算級分與五標,因此作文整整占了一半的比重,是108課綱新式學測中十分重要的改變。加上分科測驗不再考國文,學測國文直接定生死,準備作文就成了其中至關重要的一環。 但畢竟是考試作文,有評分規則與給分標準這個「拿高分的線索」,它們可以說是閱卷老師的審美和喜好,
avatar
椰林書齋Writing
2024-02-15
OP簡書評02-超棒電視影集這樣寫編劇書中討論了影集、電影的情節設計,以情節為主的觀點。 本文則偷渡了作者的一些觀影心得,以及對編劇技巧應用於寫作上的思考。 本文可能適合文字寫作者參考,對編劇則比較沒用。
Thumbnail
avatar
54OP總裁兼長工
2024-02-05
閱讀日記「故事行銷」⋯原來該這樣寫!閱讀日記「故事行銷」⋯原來該這樣寫! 這是台灣作家「李洛克」寫的書,同樣他也是名小說家跟編劇,所謂的故事行銷大家會想到什麼呢?應該是很多企業故事吧!但這些企業故事能否打動人心呢?他們的用詞精準嗎?能讓讀者感同深受嗎?很多都用自己懂的語言,譬如:週轉困難⋯沒了!誰知道「週轉困難」有多困難!他在本書中
Thumbnail
avatar
宇牛
2023-11-15
文案這樣寫,吸引來的都是死忠粉絲每個人都擁有不同的生活觀,價值觀,以及對事物的看法。當你毫不猶豫地分享自己的觀點時,你會不知不覺地吸引到一群志同道合的人,他們將成為你的忠實粉絲。 本文將告訴你如何在社群媒體中,通過表達自己的獨特觀點,吸引更多這樣的人,讓他們成為你生活的重要一部分。
Thumbnail
avatar
梅子's 拓荒者品牌學
2023-08-21
🏆 AI卡片盒寫作指南:知識煉金,你需要這套思維用好Obsidian,GPT4與雪花寫作法本文章分享我於2023年8月,結合AI與卡片盒筆記法的規模化寫作策略。
Thumbnail
avatar
王啟樺
2023-08-02
【這樣學更有效 5】你的番茄鐘工作法常常失敗嗎?4 個細節用好番茄鐘技巧你使用過番茄鐘嗎?概念很簡單,但細節很重要,不注意的話用個 1-2 次就不會想用了。這篇文章分享用好番茄鐘的 4 個細節 : (1)使用方法要簡單(2)紀錄方式要單純(3)我們有調整番茄鐘長度的權力(4)組間休息很重要,選擇你最喜歡的休息方式
Thumbnail
avatar
朱騏
2021-11-17
你以為的「個性」就是這樣嗎?|我的好書單|《個性》心得當我們投入一段關係,對方就不可避免地成為「自我」的一部分,當我們離開一段關係之後,部分「自我」就離我們而去。 這是社會心理學家布萊恩.拉沃里說的:「人際關係是自我的結構,沒有這些關係就沒有自我的概念。」 到底什麼是自我呢?什麼是每一個人的「個性」呢 你害怕沒有「做自己」嗎?
Thumbnail
avatar
陳虹君
2021-10-21
【原來好「玩」的同學是這樣的!你還沒跟上嗎?】5個不容在學生時期錯過的事提到不容在學生時期錯過的事,總是期待脫離束縛、放飛自由的感覺。無論是在學的哪個階段,大家在心中,應該都有人生待做、想完成的清單吧?而日常除了打牌、夜唱、小酌、不小心的翹課…還有什麼不容錯過的? 讓我們一同探索這個充實版本的校園人生,分享好「 玩」的同學在做什麼!
Thumbnail
avatar
TINGting's 補給站
2021-08-20
【交易風格】這樣買股票是對的嗎?左側交易還是右側交易?哪種方法比較好?怎麼股票總是一賣了就漲,買了就開始跌...其實不是你運氣不好,只是你還不了解這個觀念!了解左側交易、右側交易風格後,讓你更了解自己是哪種屬性,在對的時機買,更對的時機賣! 什麼是左側交易? 左側交易顧名思義是在左側邊交易的風格,那左側?是在什麼東西的左側勒?來,用一張圖讓你暸解! 在股票趨
Thumbnail
avatar
珈珈
2021-02-26
履歷|Ep.4|你還在這樣寫履歷嗎?快避開這種無效的寫法你還在寫類似這樣的履歷嗎?如果是的話,最好避開他們,不然很容易在求職的過程中成為沒能被看見的那份履歷,非常可惜。事實上,不是你不會寫,也不是做不到,而是沒有找到對的方法。
Thumbnail
avatar
Yo Chen
2020-05-15