Python之父:為什麼操作符很有用?
這是我在python-ideas上發布的一些東西,但我認為這些很有趣,應該分享給更多的人。
最近有很多關於合併兩個dict(詞典)的運算符的討論。
這促使我思考為什麼有些人喜歡運算符,我想起了30多年前與導師Lambert Meertens的一次討論。
對於數學家來說,運算符對於他們的思考方式至關重要。我們來選取一個簡單的操作,比如將兩個數相加,並嘗試研究它的一些行為。
add(x, y) == add(y, x) (1)
式(1)表示了加法的交換律。它通常用運算符來書寫,這使得它更簡潔:
x + y == y + x (1a)
這似乎是一個小小的收穫。
現在我們來考慮一下結合律:
add(x, add(y, z)) == add(add(x, y), z) (2)
式(2)可以用運算符重寫:
x + (y + z) == (x + y) + z (2a)
這比式(2)容易理解得多,並且我們發現括弧是多餘的,所以現在我們可以這樣寫:
x + y + z (3)
沒有歧義(+ 運算符綁定到左邊還是右邊並不重要)。
許多其他定律也可以很容易的使用運算符來寫。這裡還有一個關於加法恆等元素的例子:
add(x, 0) == add(0, x) == x (4)
相比於
x + 0 == 0 + x == x (4a)
這裡的總的思想就是一旦你學會了這個簡單的表示法,用它們寫的方程就比用函數表示法寫的方程更容易「操作」——就好像我們的大腦用不同的大腦機制來掌握運算符,這是更有效率的方法。
我認為,使用運算符編寫的公式更容易被「視覺化」處理就與此有關: 它們利用了大腦的視覺處理機制,而這一機制在很大程度上是在潛意識中運作的,並且它會告訴大腦的意識部分它看到了什麼(比如,「椅子」而不是「幾塊木頭連在一起」)。函數符號在我們的大腦中則必須走一條不同的路徑,這是無意識的(它與內容的閱讀和理解有關,這是在比視覺處理更晚的年齡段才學會/訓練的)。
當你將多個運算符結合在一起時,視覺處理的功能就會變得非常明顯。例如,考慮一下分配律:
mul (n,add(x, y)) == add(mul (n, x) mul (n, y)) (5)
這寫起來很惱火,我相信一開始你是不會看到這個規律的(或者至少你不會立刻看到它,如果我沒有提到這是分配律的話)。
與下式比較:
n * (x + y) == n * x + n * y (5a)
注意,這裡也使用了相對的運算符優先順序。通常數學家們會把它寫得更緊湊:
n(x+y) == nx+ny (5b)
但是,遺憾的是,目前這超出了Python解析器的能力。
運算符表示法的另一個非常強大的方面是,可以方便地將它們應用於不同類型的對象。例如,定律(1)到(5)在x、y和z是相同大小的向量,而n是標量(用0向量代替字面量「0」)時也適用,如果它們是矩陣(同樣,n必須是一個標量)也適用。
你可以這樣處理不同域中的對象。例如,上面的定律(1)到(5)也適用於函數(n也是一個標量)。
通過明智地選擇運算符,數學家們可以運用他們的視覺大腦來幫助他們更好地進行數學研究: 他們會更快地發現新的有趣的定律,因為有時黑板上的符號就會跳到你面前,給你提供一條通往難以捉摸的數學證明的道路。
現在,編程並不完全等同於數學,但我們都知道可讀性很重要,這就是Python中運算符重載的作用。一旦你內化了運算符具有的簡單屬性,使用+號進行字元串或列表連接將比純OO表示法更具可讀性,上面(2)和(3)解釋了(部分程度上)為什麼是這樣。
當然,這樣做絕對有可能做過火——然後你就會使用Perl。但我認為,那些指出「已經有辦法做到這一點」的人忽略了一點,即真正理解這一點是比較容易的:
d = d1 + d2
和下面相比:
d = d1.copy ()
d.update(d2) #修正:這一行之前是錯誤的
這不僅僅是少了幾行代碼的事: 第一種形式允許我們使用我們的視覺處理,以幫助我們更快的看到它的意思,並且不會影響我們大腦的其他部分(例如,這些部分可能已經被跟蹤d1和d2的意思佔據)。
當然,任何事情都是有代價的。你必須學習運算符,並且在應用於不同對象類型時必須學習它們的屬性。(數學中也是如此——對於數字,x*y == y*x,但是這個屬性不適用於函數或矩陣; 另一方面,正如結合律一樣, x+y == y+x適用於所有情況。)
「但是性能呢?」我聽見你這樣問。好問題。在我看來,可讀性第一,性能第二。在基本的例子(d = d1 + d2)中,與使用update的兩行代碼版本相比,沒有性能損失,而且可讀性明顯提高。我能想到很多情況,性能差異無關緊要,但可讀性是最重要的,對我來說,這是默認的假設(即使在Dropbox——我們最重要的性能代碼已經用醜陋的Python或Go重寫過了)。對於少數性能至關重要的情況,很容易將運算符版本轉換為其他版本——*一旦你確認了這是很有必要的*(可能是通過分析得出d的)。
英文原文:https://qiniumedia.freelycode.com/vcdn/1/%E4%BC%98%E8%B4%A8%E6%96%87%E7%AB%A0%E9%95%BF%E5%9B%BE2/why_operators_are_useful.pdf 譯者:天天向上
※支持多標籤頁的Windows終端:Fluent 終端
※理解 Python 的 for 循環
TAG:Python部落 |