好吧題目很簡單,但是有些細節還是挺有意思的。
題目是:計算今年是否是閏年,判斷閏年條件,滿足年份模400為0,或者模4為0但是模100不為0
答案是這樣的:
import time#計算今年是否是閏年,判斷閏年條件,滿足年份模400為0,或者模4為0但是模100不為0thisyear = time.localtime()[0] #擷取年份if thisyear%400==0 or thisyear%4==0 and thisyear%100<>0:print 'this year is a leap year'else:print 'this yeat is not a leap year'
很簡單的源碼,在此來記錄其中的一些細節。
先回顧一下Python中的數組,Python的數組分三種類型:
(1) list 普通的鏈表,初始化後可以通過特定方法動態增加元素。
定義方式:arr = [元素]
(2) Tuple 固定的數組,一旦定義後,其元素個數是不能再改變的。
定義方式:arr = (元素)
(2) Dictionary 詞典類型, 即是Hash數組。
定義方式:arr = {元素k:v}
接下來看看源碼。
首先是time模組,localtime()返回的是一個tuple,也就是一個固定大小的數組,數組裡是目前時間的一些資料 :
localtime([seconds]) -> (tm_year,tm_mon,tm_day,tm_hour,tm_min,tm_sec,tm_wday,tm_yday,tm_isdst)
然後是if判斷裡面的 or 和 and ,
Python的邏輯運算子裡沒有“!(非),&&(與),||(或)“,
這三個表示符號(完全是英文上的表示),即 not,and,or。
但是看源碼,判斷是否閏年應該是:
1.如果被400整除那就是閏年
2.如果能被4整除且不能被100整除
那if判斷不應該是:
if thisyear%400==0 or (thisyear%4==0 and thisyear%100<>0):
這樣的嗎?
實際上確實是這樣的,但是在Python中,and的優先順序要高於or。
我們可以來看一個小例子:
>>> if 1 or 1 and not 1:... print 'OK'...OK
如果優先順序相等應該是不會輸出,其實上面的判斷相當於:
if 1 or (1 and not 1):
也就是說,
True or True and not True 僅僅表示 (True) or (True and False)
說到這裡可以再看一個有意思的東西,來看看Python裡面的短路機制:
def a(): print 'this is A!' return 1def b(): print 'this is B!' return 1def c(): print 'this is C!' return 1if a() or b() and not c(): print 'OK!'
如果說and的優先順序要高於or,那麼豈不是應該先B再C再A,怎麼直接就輸出了A呢?
其實在其他語言中也有這樣的情況,只是當時沒有在意,這是布林運算子的一個有趣的特性。
布林運算子有個有趣的特性:只有在需要求值時才進行求值。
舉例來說,運算式x and y需要兩個變數都為真時才為真,
所以如果x為假,運算式就會立刻返回false,而不管y的值(事實上各個語言都有這個特性)。
實際上,如果x為假,運算式會返回x得值----否則它就返回y的值。
這種行為被稱為短路邏輯(short-circuit logic)或惰性求值(lazy evaluaion):
布林運算子通常被稱為邏輯運算子,就像你看到的那樣第2個值有時“被短路了”。
這種行為對於or來說也同樣適用。
在運算式x or y中,x為真時,它直接返回x的值,否則返回y值。
注意,這意味著在布林運算子之後的所有代碼都不會執行。
再看看剛剛的那個例子,and優先順序高,表明最靠近它兩邊的運算式是與的關係,這樣的組合是優先的。
很明顯,遇到第一個True,就沒必要再計算or後面的東西了,結果已經是True了。
在Python中運用and 和 or可以實現三元運算,比如在JS中的一個函數:
function trans(v) { return (v==0)?1:v; }
在Python中可以有以下兩種替換方案:
def trans(v): return 1 if v==0 else v
或者:
def trans(v): return v==0 and 1 or v
解釋一下:
如果v等於0,則跟1做與運算,為true,則不進行後面的或運算,直接返回1;
如果v等於0為false,則跟1做與運算,為false,繼續進行或運算,返回v。