標籤:
原書參考:http://www.jeffknupp.com/blog/2012/10/04/writing-idiomatic-python/
上一篇:翻譯《Writing Idiomatic Python》(二):函數、異常
下一篇:TO BE UPDATED..
2.1 變數2.1.1 對多個變數要賦同一個值時,使用鏈式賦值讓語句變得簡明
Python支援鏈式賦值使多個變數可以在一次鏈式賦值中被設定為同一個值,這使得語句更加簡明。
不良風格:
1 x = ‘foo‘2 y = ‘foo‘3 z = ‘foo‘
地道Python:
1 x = y = z = ‘foo‘
2.1.2 避免使用臨時變數來實現值交換
在Python中完全沒有必要使用一個額外的臨時變數來實現值交換。使用元組來實現不僅方便並且可讀性更強。
不良風格:
1 foo = ‘Foo‘2 bar = ‘Bar‘3 temp = foo4 foo = bar5 bar = temp
地道Python:
1 foo = ‘Foo‘2 bar = ‘Bar‘3 (foo, bar) = (bar, foo)
2.2 字串2.2.1 對字串相關的函數使用鏈式調用使意圖更簡明
當對某個字串資料進行一系列的處理時,直接在上一個調用後接下一個調用常常比起建立一系列臨時變數的方法更加明確和簡單。當然,如果鏈式調用太多也會破壞可讀性,一般來說如果操作不超過三個使用鏈式調用會更好。
不良風格:
1 book_info = ‘ The Three Musketeers: Alexandre Dumas‘2 formatted_book_info = book_info.strip()3 formatted_book_info = formatted_book_infor.upper()4 formatted_book_info = formatted_book_infor.replace(‘:‘, ‘by‘)
地道Python:
1 book_info = ‘ The Three Musketeers: Alexandre Dumas‘2 formatted_book_info = book_info.strip().upper().replace(‘:‘, ‘by‘)
2.2.2 使用‘‘.join串連列表中的字串元素
這樣做更快,佔用更低記憶體,並且這個用法在Python中非常普遍。注意下面的例子中使用的是用‘‘連接字串,實際在使用的時候可以替換為你想要的分隔字元。
不良風格:
1 result_list = [‘True‘, ‘False‘, ‘File not found‘]2 result_string = ‘‘3 for result in result_list:4 result_string += result
地道Python:
1 result_list = [‘True‘, ‘False‘, ‘File not found‘]2 result_string = ‘‘.join(result_list)
2.2.3 使用ord擷取字元的ASCII碼,使用chr從ASCII碼擷取字元
擷取一個字元的ASCII碼是一個有用的功能(比如字串散列化),相應的,從ASCII得到對應的字元也常常很有用。
Python中提供了兩個內建的函數,chr和ord,可以實現字元和ASCII碼之間的相互轉化。
不良風格:
1 hash_value = 0 2 character_hash = { 3 ‘a‘: 97, 4 ‘b‘: 98, 5 ‘c‘: 99, 6 # ... 7 ‘y‘: 121, 8 ‘z‘: 122, 9 }10 for e in some_string:11 hash_value += character_hash[e]12 return hash_value
地道Python:
1 hash_value = 02 for e in some_string:3 hash_value += ord(e)4 return hash_value
2.2.4 用format函數來進行字串格式化
一般來說又三種方式來進行字串格式化:最簡單但是最不推薦的就是用+來連接字串。另一種方式是老式的利用%來格式化字串的辦法,在其他許多語言中也能看到這種方式,比如一些語言中的printf。這種方法比用+的方法好一些。
在Python中,最地道和清晰的用法當屬用format函數來進行字串格式化。和老式的格式化方法類似,這種辦法用帶有格式的字串作為模板並用一些值替換預留位置產生最終字串。比老式的格式化方法更好的地方是,在format函數中,我們可以命名預留位置,擷取預留位置的對應變數的屬性,控制字元寬度和填充等。format函數讓字串格式化顯得簡明。
不良風格:
1 def get_formatted_user_info_worst(user):2 # Tedious to type and prone to conversion errors3 return ‘Name: ‘ + user.name + ‘, Age: ‘ + str(user.age) + ‘, Sex: ‘ + user.sex4 5 def get_formatted_user_info_slightly_better(user):6 # No visible connection between the format string placeholders7 # and values to use. Also, why do I have to know the type?8 # Don‘t these types all have __str__ functions?9 return ‘Name: %s, Age: %i, Sex: %c‘ % (user.name, user.age, user.sex)
地道Python:
1 def get_formatted_user_info(user):2 # Clear and concise. At a glance I can tell exactly what3 # the output should be. Note: this string could be returned4 # directly, but the string itself is too long to fit on the5 # page.6 output = ‘Name: {user.name}, Age: {user.age}, Sex: {user.sex}‘.format(user=user)7 return output
2.3 列表2.3.1 使用列表解析從一個列表產生新的列表
在恰當使用的情況下,列表解析會增加代碼從一個列表中建立新列表的明確性。尤其是當新建立的列表是源列表的某種變換或者條件檢查時。
除了使代碼更清晰,列表解析在執行效率上也非常高(CPython中)。
不良風格:
1 some_other_list = range(10)2 some_list = list()3 for element in some_other_list:4 if is_prime(element):5 some_list.append(element + 5)
地道Python:
1 some_other_list = range(10)2 some_list = [element + 5 for element in some_other_list if is_prime(element)]
2.3.2 使用負數下標
一個常被很多Python初用者忽視的特性是,在Python的列表和字串中是可以使用負數下標的。和正數下標從列表開頭向後數不同,附屬下標從列表的末尾往回數。
不良風格:
1 def get_suffix(word):2 word_length = len(word)3 return word[word_length - 2:]
地道Python:
1 def get_suffix(word):2 return word[-2:]
2.3.3 和內建的map()以及filter()函數相比,優先使用列表解析
Python是一門自誕生以來就一直在演化的語言。也正因為如此,一直有一些曆史遺留被保留了下來。map和filter函數就是例子,儘管曾經在一些情況下用map和filter是最佳的選擇,但是現在幾乎所有的使用都可以用列表解析來代替。並且列表解析的可讀性和清晰性更好,所以至少在我的書裡我認為應該優先使用列表解析而不是map和filter的組合。
不良風格:
1 the_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]2 def is_odd(number):3 return number % 2 == 14 odd_numbers = filter(is_odd, the_list)5 odd_numbers_times_two = list(map(lambda x: x * 2, odd_numbers))
地道Python:
1 the_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]2 odd_numbers_times_two = [n * 2 for n in the_list if n % 2 == 1]
// 其實這是個很見仁見智的問題,在stackoverflow上也有很多關於map/filter和list comprehension的爭論,就效率而言,對不同的情況下兩種辦法互有勝負,就可讀性而言其實我覺得map和filter比list comprehension好很多。。另外別忘了還有個函數叫reduce
2.3.4 使用內建的sum函數對列表中的元素求和
對於一些已經用習慣sum的人來說可能會覺得這條比較奇怪。然而對更多的Python新手而言他們做的是自己重新實現了sum函數。如果一個函數已經是內建的,那麼我們不應該重新發明輪子。
不良風格:
1 the_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]2 the_sum = 03 for element in the_list:4 the_sum += element
地道Python:
1 the_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]2 the_sum = sum(the_list)
2.3.5 使用all檢查一個可遍曆結構中是否所有元素都是真
和sum一樣,all也是一個被新手頻繁重寫的內建函數。它可以檢查一個可遍曆結構中的元素是否都為真。
不良風格:
1 def contains_zero(iterable):2 for e in iterable:3 if e == 0:4 return True5 return False
地道Python:
1 def contains_zero(iterable):2 # 0 is "Falsy," so this works3 return not all(iterable)
2.3.6 優先使用xrange而不是range,除非你需要的就是range產生的列表
xrange和range都能讓你遍曆一個數值列表。區別是,xrange不會再記憶體中儲存一個完整的列表。大多數情況下這兩者不會再實際使用時產生區別,但是當你需要遍曆的數值範圍非常大時,在記憶體佔用和執行效率上就能看到很大差別了。
不良風格:
1 # A loop over a large range that breaks out2 # early: a double whammy!3 even_number = int()4 for index in range (1000000):5 if index % 2 == 0:6 even_number = index7 break
地道Python:
1 even_number = int()2 for index in xrange(1000000):3 if index % 2 == 0:4 even_number = index5 break
轉載請註明出處:達聞西@部落格園
上一篇:翻譯《Writing Idiomatic Python》(二):函數、異常
下一篇:TO BE UPDATED..
翻譯《Writing Idiomatic Python》(三):變數、字串、列表