以下內容首發於我的個人博客網站:
http://riun.xyz
事情的前戲是今天在做一個python的小練習:利用generator生成楊輝三角時遇到一個小問題,期間由於一個錯誤足足折磨了好幾個小時。
楊輝三角大致是這樣:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-wFR1ASCJ-1590762944525)(https://s1.ax1x.com/2020/03/25/8jEjyV.jpg)]
要求輸出成這樣的形式:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-8U4Sh77Y-1590762944531)(https://s1.ax1x.com/2020/03/25/8jVVOK.jpg)]
我的代碼是這樣:
# 練習:利用generator生成器打印楊輝三角
def triangles(n):
# n = 10
preL = []
nL = [x*0 for x in range(n)]
for i in range(n): # 外循環,控制循環幾次,即 有幾行
for j in range(i+1): # 內循環,控制每行循環幾次,即每行有幾個元素
if j == 0 | j == i: # 此處應將 | 換爲 or
nL[j] = 1
else:
nL[j] = preL[j-1] + preL[j]
preL = nL[:i+1]
#print(preL)
yield preL
#yangh(5)
yh = triangles(10)
for x in yh:
print(x)
我的思路是在內循環生成nL列表,生成的時候對每行第1個元素和最後一個元素單獨處理,均賦值爲1。中間的元素取上面的列表的第j-1和第j個元素之和。
但是輸出來總是不對:
由於公司項目需要,我剛開始學python,很多語法還不熟,可勁折騰了好久才發現問題。
原來我把內層循環中處理臨界值的判斷語句搞錯了。就是if j == 0 | j == i:
這句。
我的本意是 j0 或者 ji,就是當循環到本行的第一個 或者 最後一個元素時處理。
但是錯用了 按位或| 運算符,我之前想用 || 來着,可是寫了後報錯,就換成|,不報錯了我就以爲是對的。沒想到還是錯了,應該用 邏輯運算符or。上面代碼將 | 換爲 or就完全正確了
重點就是我在排查的時候進行了如下輸出:
i = 1
j = 0
print(j==0 | j==i) # True | False = False
print(True | False) # True | False = True
>>> False
>>> True
心想,嗯?j0應該是 True,ji應該是False。那麼第一個表達式就是True | False,這不是和第二個一樣嗎,爲什麼結果還不一樣?
後來想到運算符優先級的事情,發現原來 | 比 == 優先級高。
所以第一個輸出其實是這樣:
print(0==0 | 0==1)
先運算 |
print(0==0==1)
就是這個式子,重點來了!
我本來想的是從右向左運算?那麼先運算 01,爲False,再計算0False,爲True吧
但是萬萬沒想到這個式子結果居然輸出False!
驚了~!,這是爲什麼啊?
難道是我中間過程有問題?
接着我又試着找證據證明我的過程是對的:
print(0==0==1)
print(0==False)
print(True==1)
>>> False
>>> True
>>> True
看着這個結果我陷入了沉思:
第二第三行輸出告訴我:0False 是 True ; 1True 也是 True
那第一個表達式001
如果從左向右算:
00 是True ; 然後 True == 1 是 True 啊,但是表達式結果是False
如果從右向左算:
01 是False; 然後0==False 還是True啊,但是表達式結果是False
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-5YJdJU8c-1590762944538)(https://s1.ax1x.com/2020/03/25/8jRW9K.jpg)]
我尼瑪人都傻了,!》? 這是什麼奇奇怪怪的東西?
然後我問了幾個同學,這到底是怎麼比較的啊,有的不知道,有的也理解不了。後來一個室友無意間說了句”他可能是同時算的“
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Ya8AOixX-1590762944542)(https://s1.ax1x.com/2020/03/25/8jymBq.jpg)]
我心裏一驚,欸,不是吧?好像有道理欸。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ZwuDVsQm-1590762944545)(https://s1.ax1x.com/2020/03/25/8j2qlF.jpg)]
然後我做了實驗:
print((0==0)==1)
>>> True
居然輸出True!!!!!
這樣就對了,00是True,True1還是True。結果對上了!
那麼就是說print(0==0==1)
還真是同時算的,計算三個元素是否相等!
我又做了如下輸出:
print(False==False==True)
>>> False
果然,幾個元素連着進行 == 運算,就是判斷這幾個元素是否一致啊!
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-e75u0zdN-1590762944550)(https://s1.ax1x.com/2020/03/25/8jRdpT.jpg)]
接着機智的我又想到了Java裏會是怎樣。我知道Java中
System.out.println(0==0==1);
這樣是錯誤的,因爲無論從那邊算起,都會出現int和boolean進行比較的情況出現。所以無法比較,加括號也不行。將int強轉爲boolean也不行,因爲無法強轉。
所以我就試了試這樣:
System.out.println(false==false==true);
>>> true
輸出結果是true,和python
中不同。
也就是說Java中幾個元素進行 == 運算,是從右向左進行運算,先計算falsetrue,結果是false,再計算falsefalse,結果纔是true。
總結
python
中,幾個元素進行==運算,比較的是幾個元素(的值)是否都相等,只要有一個不等,就是False,全部相等,纔是True。
而java
中對幾個元素進行==運算,是向普通運算符那樣,從右向左依次比較,得到true或者false,再與前一個比較,最後返回結果。
【上面說python
中==比較的是值,還沒有充分證明,但我感覺是這樣的。如果說比較的是地址值的話,那麼python
中在對數字或者字符串比較時,這些相同值的數字或字符串引用的就應該是同一個地址空間了】