Python貓注:Python 語言誕生 30 年了,如今的發展勢頭可謂如火如荼,這很大程度上得益於其易學易用的優秀設計,而不可否認的是,Python 從其它語言中偷師了不少。本文作者是一名資深的核心開發者,他廣博的視野和精準的認識,讓我對 Python 的設計瞭解得更為全面,同時,他“利用自豪感而非恐懼感”的說法,傳達出來的是“專注於自我的進步,不嫉妒他人的成功”的原則,對我也很有幫助。原文寫於 2015 年,躺在我的收藏夾裡很久很久了,如今順利翻譯掉,這是一件能提升自豪感的有意義的事。最後祝大家開卷有益,讀有所獲。
作者:Nick Coghlan
英文:https://www.curiousefficiency.org/posts/2015/10/languages-to-improve-your-python.html
宣告:本翻譯是出於交流學習的目的,基於 CC BY-NC-SA 4.0 授權協議。為便於閱讀,內容略有改動。
目錄
- 拓寬我們的視野
- 程式式程式設計:C、Rust、Cython
- 物件導向的資料模型:Java、C#、Eiffel
- 物件導向的 C 派生:C++、D
- 面向陣列的資料處理:MATLAB/Octave、Julia
- 統計資料分析:R
- 計算管道建模:Haskell、Scala、Clojure、F#
- 事件驅動程式設計:JavaScript、Go、Erlang、Elixir
- 漸變型別:TypeScript
- 動態超程式設計:Hy、Ruby
- 務實問題解決:Lua、PHP、Perl
- 程式設計思維:Scratch、Logo
作為世界上最流行的程式語言之一的共同設計者,我經常看到一個令人沮喪的行為(在 Python 社群和其它社群):有影響力者試圖激發人們對“敗給”其它開源社群的恐懼,從而調動人們對社群作貢獻的積極性。(我自己偶爾也會犯這種錯誤,這讓我更容易發現其他人是否也落入了同樣的陷阱)。
雖然學習其它程式語言社群的經驗是件好事,但基於恐懼的方法來激勵行動是有嚴重問題的,因為這會刺激本社群成員將其它社群的人視為爭奪開源貢獻者關注的敵人,而不是作為在更大挑戰中的潛在盟友(推動軟體開發藝術發展)。這還會告訴那些喜歡其它語言的人,在一個把他們以及他們的同伴視為“敵對競爭對手”的社群裡,他們是不受歡迎的。
事實上,我們希望有多種多樣的跨平臺的開源程式語言供選擇,因為程式語言是思考的首要工具——使我們能夠以明確的方式表達我們的想法,從而讓計算機也能夠理解。如果有人找到了一種適合大腦的語言,能夠解決眼前的問題,那就太好了,不管他們選擇的是哪種(些)語言。
因此,我對 Python 社群有三個具體的請求,以及一個較為寬泛的建議。首先,我的請求是:
- 如果我們要利用社群的本能來激勵行動,就應該避免利用恐懼感,而應該利用自豪感。 當我們將恐懼作為激勵因素時,就像在說“如果我們不做 X,就會失去開發者對 Python 的關注”,這等於是故意地在自由的開源貢獻者中創造悲觀的情緒。然而,依賴社群的自豪感就像在說“目前尚不清楚如何在 Python 中解決 X 問題。如果我們看看 Y 語言,就可以看到他們有一個非常好的方法來解決問題 X,我們可以吸收進 Python,以提供類似的舒適的使用者體驗。”積極的態度讓我們對自己的努力感到自豪,而不是貶低他人的努力,這有助於在 Python 社群內促成一種持續學習的文化,並促進與其它社群改善協作關係,共同發展。
- 剋制對其它開源程式語言社群採取輕蔑的態度,尤其當這些社群授權人們解決自己的問題,而不是等待商業軟體供應商來解決問題。 世界上大多數重要的問題解決起來都是無利可圖的(因為受苦於這些問題的人並不富裕,而且無法左右機構基金的決定),所以我們應該鼓勵試圖解決這些問題的人,不管我們如何看待他們的技術選擇。
- **如果我們認識的人剛開始學習程式設計,並且他們選了一種我們不喜歡的語言,我們應該支援他們的選擇。 **他們比我們更知道什麼適合自己,適合我們的語言不一定適合他們。如果他們對自己最初的選擇感到了沮喪,甚至已經對學習程式設計變得沒有動力,此時再給他們推薦別的程式語言。這個建議還適用於那些在改善糟糕的網路安全狀況的人:我們在面對天生不安全的語言時,採取的方法是改進作業系統的沙箱功能,逐步學習有更好的本地安全屬性的語言,並改善現有語言的預設行為,而不是列舉為什麼從程式安全性的角度來看,他們選擇的語言是一個糟糕的選擇,來迷惑初學者。(如果有人部署了由初學者編寫的未經稽核的軟體來處理安全敏感的任務,那就不是開發者的問題,而且部署者的問題,他們沒有對軟體的出處和安全屬性進行適當的盡職調查。)
我的寬泛的建議針對那些遇到了 Python 核心程式的限制,並因此希望探索 Python 中可用的“思考工具”的人。這個建議就是:
拓寬我們的視野
在開發 Python 核心程式的過程中,我們會做的一件事是檢視其它語言中解決了我們正面臨的問題的特性,看看是否有辦法既吸收它們,又使 Python 程式碼更易於閱讀和編寫。這意味著學習其它專注於特定軟體開發風格的程式語言,可以幫助我們在使用 Python 時,提高對這種程式設計風格的理解。
為了提供幫助,我在下面列出了一些值得探索的領域,以及可能加深對這些領域的理解的語言。我儘可能連結了維基百科的頁面,而不是直接連結到語言的主頁,因為維基百科經常會提供有趣的歷史背景,當你為了教育目的學習一門新的程式語言,而不是直接用於實際應用時,這些背景值得去了解。
雖然我知道這些語言中的大部分(並且在開發生產系統時使用過幾種),但這份推薦清單中還包括我間接知道的語言(通常是通過閱讀教程和設計文件,或者通過與我信任的人交談,以獲取對一門語言的優點與缺陷的洞察)。
還有很多本應該放但沒有放進名單裡的語言語言,所以下面羅列的僅是我感興趣的部分(例如,我主要感興趣的是 Linux、Android 和 Windows 的生態系統,所以我捨棄了 Apple 生態中的 Objective-C 和 Swift 語言,另外我也不熟悉 Processing 這種專注於藝術的程式語言,無法想象學習它們能教給 Python 開發者什麼)。
除了考慮一門語言可能教給你的東西,如果你想獲得一份更全面的清單,可以去檢視 IEEE Spectrum 關於程式語言流行度和增長度的年度榜單。
程式式程式設計:C、Rust、Cython
Python 預設的執行模型是過程式的:從主模組的頂部開始,逐條語句地執行。Python 對下面介紹的所有資料和程式設計建模方法的支援,都建立在這種過程式的執行模型上。
C 語言仍然是無可爭議的底層程式式程式設計的統治者。它是 Python 官方直譯器以及 Linux 作業系統核心的核心實現語言。作為一名軟體開發人員,學習 C 語言是更多地瞭解底層硬體的最好方法之一——C 語言經常被稱為“可移植的組合語言”,對於任何新的 CPU 架構來說,第一個交叉編譯的應用程式將是 C 編譯器。
Rust 是一種相對較新的程式語言,由 Mozilla 創造。Rust 的目標是吸取整個行業在不使用 C 時遇到的所有教訓,設計一門能與 C 庫相互操作的新語言,提供底層的系統程式設計所需的對硬體用途的精確控制,但使用不同的編譯方法來進行資料建模和記憶體管理,從結構上消除許多困擾 C 程式的常見缺陷(如緩衝區溢位、指標重複釋放錯誤、空指標訪問和執行緒同步問題)。經過培訓和早期的專業經驗,我是一名嵌入式系統工程師,而 Rust 是我見過的第一種看起來有潛力縮減當前由 C 語言和自定義彙編程式碼所主導的生態位的新語言。
Cython 也是一種較底層的過程式語言,但與 C 和 Rust 等通用語言不同,Cython 專門用於編寫 CPython 的擴充套件模組。為了實現這一目標,Cython 被設計為 Python 的超集,允許程式設計師選擇何時支援純 Python 語法以獲得靈活性,何時支援 Cython 的語法擴充套件,以便生成在速度和記憶體效率方面能與原生 C 程式碼相當的程式碼。
學習這些語言,你可以加深在記憶體管理、演算法效率、二進位制介面(ABI)相容性、軟體可移植性、以及將原始碼轉換為執行系統等實踐方面的見解。
物件導向的資料模型:Java、C#、Eiffel
程式設計最主要做的事情之一是為現實世界建模,最流行的做法是提供原生的語法支援物件導向程式設計:對資料作結構化的分組,使用類方法操作那些資料結構。
Python 本身是經過精心設計的,無需先編寫自己的類就可以使用物件導向的特性。並不是每種語言都採用這種方法——本小節中列出的語言都認為學習物件導向設計是使用該語言的必要條件。
在 20 世紀 90 年代中後期,Sun Microsystems 公司進行了一次大規模的市場推廣,Java 成為了許多高等院校中電腦科學入門課的預設語言。雖然如今在許多教學活動中,Java 已經被 Python 所取代,但它仍然是開發商用程式時最流行的語言之一。還有一些基於通用 JVM(Java 虛擬機器)執行時的語言,例如 Python 的 Jython 實現。Android 系統的 Dalvik 和 ART 環境則是基於 Java 開放的 API 二次開發。
C# 在許多方面與 Java 相似,在 Sun 和微軟未能解決他們關於微軟的 Java 實現(即 J++)的業務差異之後,C# 成為了一種替代方案。像 Java 一樣,這是一門開發商用程式的流行語言,還有其它一些語言共享著 .NET CLR(公共語言執行時),包括 Python 的 IronPython 實現 (最早的 IronPython 1.0 的核心元件被提取成了與語言無關的 .NET 動態語言執行庫)。在很長一段時間裡,. NET 是一種專用於 Windows 的技術,而 mono 作為一種跨平臺的開源實現,但微軟在 2015 年初轉向了開源生態系統戰略。
與此清單中的大多數語言不同,我不推薦在日常工作中使用 Eiffel。但是,我依然推薦學習它,因為它教會了我許多關於良好的物件導向設計的知識,比如它認為“可驗證的正確性”是應用程式的設計目標。(學習 Eiffel 也讓我明白了為什麼“可驗證的正確性”並不是大多數軟體開發時的設計目標,因為可驗證的正確軟體實在不能很好地處理模糊性,並且完全不適用於那些你不清晰相關的約束條件卻需要給自己留下足夠的迴旋餘地,以便能夠通過迭代開發找出更具體的細節的情況。)
學習這些語言,你可以深入瞭解繼承模型、契約式設計、類不變性(class invariant)、前置條件、後置條件、協方差、逆變、類方法解析順序、泛型程式設計以及其它適用於 Python 型別系統的概念。還有很多標準庫模組和第三方框架使用這種“看得見的物件導向”的設計風格,比如 unittest 和 logging 模組,以及 Django 框架中基於類的檢視。
物件導向的 C 派生:C++、D
CPython 執行環境可以被視為一個“帶有物件的 C”的程式設計環境——在其核心,CPython 使用 C 的方法實現物件導向程式設計,即定義 C 結構體來儲存相關的資料,並將結構體的例項作為第一個引數傳遞給函式,然後對資料進行操作(這就是 CPython C API 中全能的 PyObject * 指標)。這種設計模式對應到 Python 層面,就是例項方法的顯式 self 引數以及類方法的顯式 cls 引數。
C++ 的目標是保持與 C 語言原始碼的完全相容,同時新增更高階的特性,例如支援原生的物件導向程式設計和基於模板的超程式設計。它是出了名的冗長和難以程式設計(儘管 2011 年對語言標準的更新解決了許多糟糕的問題),但它也是許多領域的程式設計首選,包括 3D 建模的圖形化引擎和跨平臺應用的開發框架(例如 Qt)。
D 語言也很有趣,因為它與 C++ 的關係類似於 Rust 與 C 的關係:它的目標是保留 C++ 的大多數令人滿意的特性,同時也避免它的許多問題(如缺乏記憶體安全)。不像 Rust,D 不是一種從頭開始設計的新程式語言——恰恰相反,D 是 C++ 的衍生物,雖然它不像 C++ 一樣是一個嚴格的 C 超集,但它遵循著一個設計原則,即任何落入 C 和 D 的共同子集的程式碼,在兩種語言中必須要表現一致。
學習這些語言,你可以更深入地瞭解將高階語言的特性與底層 C 執行時模型相結合的複雜性。學習 C++,在 Python 中操作用 C++ 編寫的庫和工具包時,也可能會有幫助。
面向陣列的資料處理:MATLAB/Octave、Julia
面向陣列的程式設計是為了支援數值程式設計模型:那些基於矩陣代數和相關數值方法的模型。
雖然 Python 的標準庫不直接支援這一點,但 Python 在設計時考慮了面向陣列的程式設計,並專門為第三方 NumPy 庫和類似的面向陣列的工具新增了一系列語法和語義特性。
在許多方面,Python 的科學技術棧 被作為商業 MATLAB 的替代方案,後者被廣泛用於科學和工程領域的建模、模擬和資料分析。GNU Octave 是一個開源的方案,目標是相容 MATLAB 程式碼的語法,允許人們對照這兩種面向陣列的程式設計方法。
Julia 是另一種相對較新的語言,重點關注面向陣列的程式設計和基於型別的函式過載。
學習這些語言,你可以瞭解 Python 的科學技術棧,以及有機會通過像 OpenCL 和 Nvidia 的 CUDA 這種技術來探索硬體層面的並行執行,並通過 Apache Spark 和專用於 Python 的 Blaze 來了解分散式資料處理。
統計資料分析:R
隨著對大型資料集的接觸越來越多,對靈活處理這些資料集的分析工具的需求也越來越大。R 程式語言就是這樣的工具,它特別關注統計性的資料分析和視覺化。
學習 R 能會讓你深入瞭解 Python 在科學技術棧的統計分析能力,尤其是 pandas 資料處理庫和 seaborn 統計視覺化庫。
計算管道建模:Haskell、Scala、Clojure、F#
物件導向的資料建模和麵向陣列的資料處理主要關注靜態的資料,無論是以命名的屬性形成集合的形式,還是以結構化資料形成陣列的形式。
相比之下,函數語言程式設計語言強調以計算流的形式對動態資料進行建模。即便只學習函數語言程式設計的基本知識,也能極大地改進資料轉換操作的結構,即使在其它過程式、物件導向或面向陣列的程式中也是如此。
Haskell 是一種函數語言程式設計語言,對 Python 的設計產生了重大影響,最顯著的是在 Python 2.0 中引入的列表推導式。
Scala 是一種(存疑的)JVM 函數語言程式設計語言,加上 Java、Python 和 R,它們是 Apache Spark 資料分析平臺的四種主要程式語言。儘管 Scala 的設計偏重於函數語言程式設計,但它的語法、資料模型和執行模型的設計也最大限度地降低 Java 程式設計師使用的門檻(因此所謂“存疑的”——其實是因為,Scala 最好被歸類為一門具有強函數語言程式設計支援的物件導向程式語言)。
Clojure 是另一種基於 JVM 的函數語言程式設計語言,是 Lisp 的一種方言。它之所以出現在這份清單裡,因為它是 Python 的 toolz 函數語言程式設計工具包的靈感來源。
F# 不是我自己特別熟悉的語言,但它作為 .net CLR(公共語言執行時)推薦的函數語言程式設計語言,所以還是值得關注。
學習這些語言,你可以深入瞭解 Python 自己的計算管道建模工具,包括容器推導式、生成器、生成器表示式、functools 和 itertools 標準庫,以及第三方的 Python 函式工具包,比如 toolz。
事件驅動程式設計:JavaScript、Go、Erlang、Elixir
計算管道是處理資料轉換和分析問題的一種極佳的方法,但許多問題需要程式作為永續性服務執行,等待事件發生,然後處理那些事件。在這類服務中,為了能夠同時容納多個使用者(或多個操作),通常必須要併發地處理多個事件。
JavaScript 最初是作為 Web 瀏覽器的事件處理語言而開發的,允許網站開發者在本地響應客戶端操作(如滑鼠點選和按鍵敲擊)和事件(如網頁完成了渲染)。所有現代瀏覽器都支援它,它與 HTML5 領域物件模型(DOM)一起,已經成為一種定義使用者介面外觀和行為的事實上的標準。
Go 是谷歌設計的一種用於建立高度可伸縮的 Web 服務的專用語言,並且已經被證明是一種非常適合開發命令列應用程式的語言。從程式語言設計的角度來看,Go 最有趣的方面是在其核心併發模型中使用了通訊順序程式(Communicating Sequential Processes)概念。
Erlang 是由愛立信設計的專用語言,用於建立高度可靠的電話交換機以及類似的裝置。它被用於開發出了流行的 RabbitMQ 訊息代理中介軟體。Erlang 使用 Actor 模型作為核心的併發原語,在執行執行緒之間傳遞訊息,而不是讓它們直接共享資料。雖然我從未用過 Erlang 程式設計,但我的第一份全職工作涉及一個基於 Actor 的 C++ 併發框架,而該框架由一名前愛立信工程師開發,另外,我自己也開發了一個這樣的框架,基於德州儀器(Texas Instrument)的輕量級 DSP/BIOS 執行時(現在的 TI-RTOS)裡面的 TSK (Task)和 MBX (Mailbox)原語。
Elixir 出現在這份清單裡,因為它被設計執行在 Erlang VM 上,提供了與 Erlang 相同的併發語義,同時還提供了一系列在語言層面上的特性,打造出一個更加全面的環境,更有可能吸引其它語言例如 Python、Java 或 Ruby 的開發者。
學習這些語言,你可以深入瞭解 Python 對併發和並行的支援,包括原生協程、基於生成器的協程、concurrent.futures 和 asyncio 標準庫模組、第三方網路服務開發框架(如 twisted 和 Tornado)、Django 中引入的 channel 概念、GUI 框架中的事件處理迴圈。Python進階
漸變型別:TypeScript
在 Python 3.5 中出現的一個比較有爭議的特性是新引入的 typing 模組,它為 Python 生態帶來了一個支援漸變型別的標準詞典。
Python貓注:Gradual typing 是 Jeremy Siek 和 Walid Taha 在 2006 年提出的理論,允許程式中同時出現動態型別與靜態型別。國內有人將其翻譯為“漸進型別”、“漸近型別”、“漸進定型”、“動靜混合型別”等等,但我覺得並不夠好。漸變型別也許是我的首創,借鑑自 Photoshop 的漸變顏色,表達出從動態型別到靜態型別的過渡(或者說交融共處的)特點。“漸變”一詞有打破界限分明的狀態(如大小、遠近、明暗),從而達到中和狀態的含義。
對於那些主要從 C、C++ 和 Java 等語言中接觸靜態型別的人來說,這似乎是一個令人吃驚的糟糕特性(因此引發了爭議)。
微軟的 TypeScript 為 Javascript 程式提供了漸變型別,因此它能更好地解釋這個概念。TypeScript 程式碼會被編譯成 JavaScript 程式碼(然後就不包含執行時型別檢查),流行的 JavaScript 庫的 TypeScript 註解會維護在專用的 DefinitelyTyped 倉中。
正如 Chris Neugebauer 在澳大利亞 PyCon 演講 中指出的,這很像是 Python 與 typeshed 型別提示庫、以及像 mypy 這種型別推斷和分析工具之間的關係。
在本質上,TypeScript 和 Python 中的型別提示都是編寫特定種類的測試的方式,要麼使用單獨的檔案(就像普通測試一樣),要麼嵌入在程式碼體中(就像靜態型別語言中的型別宣告一樣)。對於這兩種情況,你都要執行一個單獨的命令,來檢查其餘程式碼是否與已新增的型別斷言一致(對於 TypeScript,這是在編譯成 JavaScript 時隱式地發生的;對於 Python 的型別提示,這是一個完全可選的靜態分析任務)。
動態超程式設計:Hy、Ruby
C、C++、C# 和 Java 等語言的學習者在接觸 Python 時,經常感到不安的一個特性是“程式碼即資料”(code is data):函式和類之類的東西是執行時物件,可以像其它物件一樣被操縱。
Hy 是一種 Lisp 方言,可以同時在 CPython VM 和 PyPy VM 上執行。Lisp 及其方言將“程式碼即資料”的概念推到了極致,因為 Lisp 程式碼由巢狀列表組成,這些列表描述了要執行的操作(這門語言的名稱本身就代表列表處理器“LISt Processor”)。Lisp 風格語言的強大之處在於,它讓你非常容易編寫出自己的領域特定程式碼。Lisp 風格語言的最大缺點是,它讓你非常容易編寫出自己的領域特定程式碼,但這可能導致每個人寫的程式碼變得難以閱讀。
Ruby 語言在許多方面與 Python 相似,但對於 Python 中“支援但不鼓勵”的動態超程式設計特性,Ruby 社群則相對開放。這包括在已有類定義中新增新的方法,以及使用閉包來實現語言的核心結構,例如迭代。(Python貓注:關於兩種語言中迭代結構的實現對比,可閱讀 這篇文章)
學習這些語言,可以讓你深入瞭解 Python 自己的動態超程式設計特性,包括函式和類裝飾器、猴子補丁、unittest.mock 標準庫、以及像 wrapt 這樣的第三方物件代理模組。(我不知道學習哪種語言可以深入瞭解 Python 的元類系統,如果有人在這方面有任何建議,請在評論中告知我。Python 的元類驅動著很多特性,例如核心的型別系統、抽象基類、列舉型別和漸變型別表示式的執行時求值。)
務實問題解決:Lua、PHP、Perl
主流的程式語言並不是孤立存在的——它們作為一個更大的生態系統的一部分而存在,這個生態系統由發行者(企業和社群組織)、終端使用者、框架開發者、工具開發者、教育工作者等等組成。
Lua 是一種流行的程式語言,作為一種指令碼引擎嵌入到大型程式中。標誌性的例子是它被魔獸世界遊戲用來編寫客戶端外掛,它也被嵌入到了許多 Linux 發行版所使用的 RPM 元件中。與 CPython 相比,Lua 執行時的大小通常只有 CPython 的十分之一,而且由於較弱的自省能力,它更容易與程式的其它部分以及伺服器的作業系統隔離開來。Lua 社群對 Python 生態的一個顯著貢獻是 LuaJIT FFI(Foreign Function Interface 外來函式介面),它被 CPython 和 PyPy 採用,作為支援 JIT 的 cffi 介面庫的基礎。
PHP 是另一種流行的程式語言,作為 Linux-Apache-MySQL-PHP LAMP 技術棧中的“P”而崛起,因為它專注於生成 HTML 頁面,並且在早期的虛擬專用伺服器(Virtual Private Server,簡稱 VPS) 提供商中廣泛使用。儘管其設計上有諸多的概念性缺陷讓人感到絕望,但它如今是幾個極其流行的開源 Web 服務的基礎,包括 Drupal 內容管理系統、Wordpress 部落格引擎和維基百科的 MediaWiki 引擎。PHP 還支撐著一些重要的服務,比如 Ushahidi 平臺,它是一個開源的社會化新聞釋出社群。
像 PHP 一樣,Perl 也是基於 Linux 而崛起。但跟 PHP 專門作為 Web 開發平臺不同,Perl 是系統管理員的工具,在基於文字的 Linux 作業系統中,它使用正規表示式將命令的輸出轉成字串,並進行操作。當 sh、awk 和 sed 都無法勝任某些任務時,Perl 出現並派上了用場。
學習這些語言,在程式語言設計方面,不大可能獲得什麼漂亮審美或者優雅概念。學習它們,最可能的是瞭解程式語言在現實中是如何被分發和採用的,以及這些在多大程度上取決於偶然的機會、歷史意外事件、以及發行商在系統中預設整合而降低了使用門檻,而不是取決於語言本身固有的能力。Python進階
特別是,它可以提供對以下專案的重要性的洞察:CKAN、OpenStack NFV、Blender、SciPy、OpenMDAO、PyGMO、PyCUDA、樹莓派基金會和 Python 被大量商業組織採用,以保護它們在 Python 生態中不斷的投入。
程式設計思維:Scratch、Logo
我經常跟函數語言程式設計以及物件導向程式設計的擁護者們討論,他們聲稱這類語言就像過程式語言一樣易於學習。
如果我們談論的是通過嵌入式程式設計(例如機器人)進行教學,在軟體中建模的物件都有現實世界的對應物,比如學生們可以觸控的感測器、馬達和繼電器,那麼,那我會認為 OOP 的人有一定的道理。
但是對於其他人,我現在有一個標準的挑戰:拿起一本烹飪書,把其中一個食譜翻譯成你認為是容易學習的程式語言,然後找一個能理解烹飪書中語言的學生,讓其按照翻譯好的食譜操作。其實,他們不需要真正地操作下去——只需做一個思想實驗,就足以意識到他們聲稱的“很容易學”是假設了多少先驗知識。(我很期待看到學術研究人員在現實中做這種研究——我真的很希望看到結果)
另一種解決這個問題的方法是去學習那些實際上被用來教孩子們程式設計思維的語言。
其中最受歡迎的是 Scratch,它使用了拖放程式設計介面,讓學生們操縱一個獨立的圖形環境,它裡面的電子圖形可以移動,並響應環境中的事件。像 Scratch 這樣的圖形環境就相當於我們用來教孩子閱讀和書寫的圖畫書。
使用特殊的教育語言來操作圖形環境的想法並不新鮮,最早的例子之一是 1960 年代發明的 Logo 環境。在 Logo 中(以及類似的環境,如 Python 的 turtle 模組),你主要打交道的是一個“烏龜(turtle)”,你可以通過繪製線條來指導它移動和修改環境。這樣的話,命令序列、重複和狀態(例如,“起筆”、“落筆”)可以基於人們的自然直覺來使用(“想象你是那隻烏龜,如果你右轉 90 度會發生什麼?”)
回顧並重新學習這些語言,有助於有經驗的程式設計師放下固化的觀念:它們所用的概念可以提醒我們,這些概念是我們如今認為理所當然的,但初學者們需要先學習。當這樣做的時候,我們能夠更好地與學生和其他初學者們相處,因為我們更有可能開啟邏輯的枷鎖,也不會再忽略那些有必要的學習步驟。
譯者附註:以上就是全部的譯文。我還翻譯過不少優質的文章,分享近期的幾篇如下:
1、通過 for 迴圈,比較 Python 與 Ruby 程式設計思想的差別
2、Python 官方研討會:徹底移除 GIL 真的可行麼?
4、深入 Python 直譯器原始碼,我終於搞明白了字串駐留的原理!
5、為什麼 Python 沒有函式過載?如何用裝飾器實現函式過載?
如果你覺得本文有幫助,請點贊+關注支援一下啦,謝謝!